File indexing completed on 2025-02-09 06:04:45
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 KMY import / export. 0008 * 0009 * @author Stephane MANKOWSKI / Guillaume DE BURE 0010 */ 0011 #include "skgimportpluginkmy.h" 0012 0013 #include <kcompressiondevice.h> 0014 #include <kpluginfactory.h> 0015 0016 #include <qdom.h> 0017 #include <qmath.h> 0018 0019 #include "skgbankincludes.h" 0020 #include "skgimportexportmanager.h" 0021 #include "skgobjectbase.h" 0022 #include "skgpayeeobject.h" 0023 #include "skgservices.h" 0024 #include "skgtraces.h" 0025 0026 /** 0027 * Transactions treated. 0028 */ 0029 QSet<QString> SKGImportPluginKmy::m_opTreated; 0030 0031 /** 0032 * Map id / unit. 0033 */ 0034 QMap<QString, SKGUnitObject> SKGImportPluginKmy::m_mapIdUnit; 0035 0036 /** 0037 * Map id / account. 0038 */ 0039 QMap<QString, SKGAccountObject> SKGImportPluginKmy::m_mapIdAccount; 0040 0041 /** 0042 * Map id / category. 0043 */ 0044 QMap<QString, SKGCategoryObject> SKGImportPluginKmy::m_mapIdCategory; 0045 0046 /** 0047 * Map id / payee. 0048 */ 0049 QMap<QString, SKGPayeeObject> SKGImportPluginKmy::m_mapIdPayee; 0050 0051 /** 0052 * This plugin factory. 0053 */ 0054 K_PLUGIN_CLASS_WITH_JSON(SKGImportPluginKmy, "metadata.json") 0055 0056 SKGImportPluginKmy::SKGImportPluginKmy(QObject* iImporter, const QVariantList& iArg) 0057 : SKGImportPlugin(iImporter) 0058 { 0059 SKGTRACEINFUNC(10) 0060 Q_UNUSED(iArg) 0061 } 0062 0063 SKGImportPluginKmy::~SKGImportPluginKmy() 0064 = default; 0065 0066 bool SKGImportPluginKmy::isImportPossible() 0067 { 0068 SKGTRACEINFUNC(10) 0069 return isExportPossible(); 0070 } 0071 0072 SKGError SKGImportPluginKmy::importSecurities(QDomElement& docElem) 0073 { 0074 SKGError err; 0075 QDomElement securities = docElem.firstChildElement(QStringLiteral("SECURITIES")); 0076 if (!err && !securities.isNull()) { 0077 SKGTRACEINRC(10, "SKGImportPluginKmy::importFile-SECURITIES", err) 0078 QDomNodeList securityList = securities.elementsByTagName(QStringLiteral("SECURITY")); 0079 int nb = securityList.count(); 0080 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import units"), nb); 0081 for (int i = 0; !err && i < nb; ++i) { 0082 QDomElement security = securityList.at(i).toElement(); 0083 QString unitName = security.attribute(QStringLiteral("name")); 0084 0085 // We try a creation 0086 SKGUnitObject unitObj(m_importer->getDocument()); 0087 SKGUnitObject::createCurrencyUnit(m_importer->getDocument(), unitName, unitObj); 0088 0089 if (!err && (unitObj.getID() == 0)) { 0090 // Creation of unit 0091 err = unitObj.setName(unitName); 0092 QString symbol = security.attribute(QStringLiteral("symbol")); 0093 if (symbol.isEmpty()) { 0094 symbol = unitName; 0095 } 0096 IFOKDO(err, unitObj.setSymbol(symbol)) 0097 IFOKDO(err, unitObj.setCountry(security.attribute(QStringLiteral("trading-market")))) 0098 IFOKDO(err, unitObj.setType(SKGUnitObject::SHARE)) 0099 IFOK(err) { 0100 // Set pairs 0101 QDomNodeList pairList = security.elementsByTagName(QStringLiteral("PAIR")); 0102 int nb2 = pairList.count(); 0103 for (int j = 0; !err && j < nb2; ++j) { 0104 QDomElement pair = pairList.at(j).toElement(); 0105 if (pair.attribute(QStringLiteral("key")).toLower() == QStringLiteral("kmm-security-id")) { 0106 err = unitObj.setInternetCode(pair.attribute(QStringLiteral("value"))); 0107 } 0108 } 0109 } 0110 IFOKDO(err, unitObj.save()) 0111 } 0112 0113 m_mapIdUnit[security.attribute(QStringLiteral("id"))] = unitObj; 0114 0115 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 0116 } 0117 0118 SKGENDTRANSACTION(m_importer->getDocument(), err) 0119 } 0120 return err; 0121 } 0122 0123 SKGError SKGImportPluginKmy::importPrices(QDomElement& docElem) 0124 { 0125 SKGError err; 0126 QDomElement prices = docElem.firstChildElement(QStringLiteral("PRICES")); 0127 if (!err && !prices.isNull()) { 0128 SKGTRACEINRC(10, "SKGImportPluginKmy::importFile-PRICES", err) 0129 QDomNodeList pricepairList = prices.elementsByTagName(QStringLiteral("PRICEPAIR")); 0130 int nb = pricepairList.count(); 0131 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import units"), nb); 0132 for (int i = 0; !err && i < nb; ++i) { 0133 QDomElement pricepair = pricepairList.at(i).toElement(); 0134 0135 SKGUnitObject unitObj = m_mapIdUnit.value(pricepair.attribute(QStringLiteral("from"))); 0136 if (unitObj.getID() != 0) { 0137 // Unit is existing 0138 QDomNodeList pricesList = pricepair.elementsByTagName(QStringLiteral("PRICE")); 0139 int nb2 = pricesList.count(); 0140 for (int j = 0; !err && j < nb2; ++j) { 0141 QDomElement price = pricesList.at(j).toElement(); 0142 0143 SKGUnitValueObject unitValObj; 0144 err = unitObj.addUnitValue(unitValObj); 0145 IFOKDO(err, unitValObj.setDate(QDate::fromString(price.attribute(QStringLiteral("date")), QStringLiteral("yyyy-MM-dd")))) 0146 IFOKDO(err, unitValObj.setQuantity(toKmyValue(price.attribute(QStringLiteral("price"))))) 0147 IFOKDO(err, unitValObj.save(true, false)) 0148 } 0149 } 0150 0151 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 0152 } 0153 0154 SKGENDTRANSACTION(m_importer->getDocument(), err) 0155 } 0156 return err; 0157 } 0158 0159 SKGError SKGImportPluginKmy::importInstitutions(QMap<QString, SKGBankObject>& mapIdBank, QDomElement& docElem) 0160 { 0161 SKGError err; 0162 QDomElement institutions = docElem.firstChildElement(QStringLiteral("INSTITUTIONS")); 0163 if (!err && !institutions.isNull()) { 0164 SKGTRACEINRC(10, "SKGImportPluginKmy::importFile-INSTITUTIONS", err) 0165 QDomNodeList institutionList = institutions.elementsByTagName(QStringLiteral("INSTITUTION")); 0166 int nb = institutionList.count(); 0167 for (int i = 0; !err && i < nb; ++i) { 0168 // Get bank object 0169 QDomElement bank = institutionList.at(i).toElement(); 0170 SKGBankObject bankObject(m_importer->getDocument()); 0171 err = bankObject.setName(bank.attribute(QStringLiteral("name"))); 0172 IFOKDO(err, bankObject.setNumber(bank.attribute(QStringLiteral("sortcode")))) 0173 IFOKDO(err, bankObject.save()) 0174 mapIdBank[bank.attribute(QStringLiteral("id"))] = bankObject; 0175 } 0176 } 0177 return err; 0178 } 0179 0180 SKGError SKGImportPluginKmy::importPayees(QMap<QString, SKGPayeeObject>& mapIdPayee, QDomElement& docElem) 0181 { 0182 SKGError err; 0183 QDomElement payees = docElem.firstChildElement(QStringLiteral("PAYEES")); 0184 if (!err && !payees.isNull()) { 0185 SKGTRACEINRC(10, "SKGImportPluginKmy::importFile-PAYEES", err) 0186 QDomNodeList payeeList = payees.elementsByTagName(QStringLiteral("PAYEE")); 0187 int nb = payeeList.count(); 0188 for (int i = 0; !err && i < nb; ++i) { 0189 // Get account object 0190 QDomElement payee = payeeList.at(i).toElement(); 0191 QDomElement address = payee.firstChildElement(QStringLiteral("ADDRESS")); 0192 SKGPayeeObject payeeObject; 0193 err = SKGPayeeObject::createPayee(m_importer->getDocument(), payee.attribute(QStringLiteral("name")), payeeObject); 0194 IFOK(err) { 0195 QString add = address.attribute(QStringLiteral("street")) % ' ' % address.attribute(QStringLiteral("postcode")) % ' ' % address.attribute(QStringLiteral("city")) % ' ' % address.attribute(QStringLiteral("state")) % ' ' % address.attribute(QStringLiteral("telephone")); 0196 add.replace(QStringLiteral(" "), QStringLiteral(" ")); 0197 err = payeeObject.setAddress(add.trimmed()); 0198 IFOKDO(err, payeeObject.save()) 0199 } 0200 IFOK(err) { 0201 mapIdPayee[payee.attribute(QStringLiteral("id"))] = payeeObject; 0202 } 0203 } 0204 } 0205 return err; 0206 } 0207 0208 SKGError SKGImportPluginKmy::importTransactions(QDomElement& docElem, SKGAccountObject& kmymoneyTemporaryAccount, QMap<QString, SKGPayeeObject>& mapIdPayee) 0209 { 0210 SKGError err; 0211 SKGTRACEINRC(10, "SKGImportPluginKmy::importFile-TRANSACTION", err) 0212 QDomNodeList transactionList = docElem.elementsByTagName(QStringLiteral("TRANSACTION")); 0213 int nb = transactionList.count(); 0214 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import transactions"), nb); 0215 QVector<QDomNode> suboperationsList; 0216 for (int i = 0; !err && i < nb; ++i) { 0217 // Get transaction object 0218 QDomElement operation = transactionList.at(i).toElement(); 0219 0220 SKGOperationObject operationObj; 0221 err = kmymoneyTemporaryAccount.addOperation(operationObj, true); 0222 IFOKDO(err, operationObj.setDate(QDate::fromString(operation.attribute(QStringLiteral("postdate")), QStringLiteral("yyyy-MM-dd")))) 0223 IFOKDO(err, operationObj.setComment(operation.attribute(QStringLiteral("memo")))) 0224 IFOKDO(err, operationObj.setImported(true)) 0225 IFOKDO(err, operationObj.setImportID("KMY-" % operation.attribute(QStringLiteral("id")))) 0226 IFOK(err) { 0227 QString unitName = operation.attribute(QStringLiteral("commodity")); 0228 if (unitName.isEmpty()) { 0229 unitName = QStringLiteral("??"); 0230 } 0231 SKGUnitObject unit(m_importer->getDocument()); 0232 err = unit.setName(unitName); 0233 IFOKDO(err, unit.setSymbol(unitName)) 0234 IFOK(err) { 0235 if (unit.exist()) { 0236 err = unit.load(); 0237 } else { 0238 err = unit.save(); 0239 } 0240 0241 IFOKDO(err, operationObj.setUnit(unit)) 0242 } 0243 } 0244 IFOKDO(err, operationObj.save(false, false)) 0245 0246 // Is it a schedule ? 0247 IFOK(err) { 0248 QDomElement recu = operation.parentNode().toElement(); 0249 if (recu.tagName() == QStringLiteral("SCHEDULED_TX")) { 0250 // Yes ==> creation of the schedule 0251 IFOKDO(err, operationObj.load()) 0252 IFOKDO(err, operationObj.setTemplate(true)) 0253 IFOKDO(err, operationObj.save(true, false)) 0254 0255 // Yes ==> creation of the schedule 0256 SKGRecurrentOperationObject recuObj; 0257 IFOKDO(err, operationObj.addRecurrentOperation(recuObj)) 0258 IFOKDO(err, recuObj.setDate(operationObj.getDate())) 0259 IFOKDO(err, recuObj.autoWriteEnabled(recu.attribute(QStringLiteral("autoEnter")) == QStringLiteral("1"))) 0260 IFOKDO(err, recuObj.setAutoWriteDays(0)) 0261 0262 int occu = SKGServices::stringToInt(recu.attribute(QStringLiteral("occurenceMultiplier"))); 0263 QString occuType = recu.attribute(QStringLiteral("occurence")); // krazy:exclude=spelling 0264 SKGRecurrentOperationObject::PeriodUnit period; 0265 if (occuType == QStringLiteral("32") || 0266 occuType == QStringLiteral("1024") || 0267 occuType == QStringLiteral("256") || 0268 occuType == QStringLiteral("8192")) { 0269 period = SKGRecurrentOperationObject::MONTH; 0270 } else if (occuType == QStringLiteral("1")) { 0271 period = SKGRecurrentOperationObject::DAY; 0272 IFOKDO(err, recuObj.timeLimit(true)) 0273 IFOKDO(err, recuObj.setTimeLimit(1)) 0274 } else if (occuType == QStringLiteral("2")) { 0275 period = SKGRecurrentOperationObject::DAY; 0276 } else if (occuType == QStringLiteral("4")) { 0277 period = SKGRecurrentOperationObject::WEEK; 0278 } else if (occuType == QStringLiteral("18")) { 0279 period = SKGRecurrentOperationObject::WEEK; 0280 occu *= 2; 0281 } else { 0282 period = SKGRecurrentOperationObject::YEAR; 0283 } 0284 0285 IFOKDO(err, recuObj.setPeriodIncrement(occu)) 0286 IFOKDO(err, recuObj.setPeriodUnit(period)) 0287 0288 IFOK(err) { 0289 QString endDate = recu.attribute(QStringLiteral("endDate")); 0290 if (!endDate.isEmpty()) { 0291 IFOKDO(err, recuObj.timeLimit(true)) 0292 IFOKDO(err, recuObj.setTimeLimit(QDate::fromString(recu.attribute(QStringLiteral("endDate")), QStringLiteral("yyyy-MM-dd")))) 0293 } 0294 } 0295 0296 if (occuType == QStringLiteral("1") && !recu.attribute(QStringLiteral("lastPayment")).isEmpty()) { 0297 // Single schedule already done 0298 IFOKDO(err, recuObj.timeLimit(true)) 0299 IFOKDO(err, recuObj.setTimeLimit(0)) 0300 } 0301 IFOKDO(err, recuObj.save(true, false)) 0302 } 0303 } 0304 0305 // Get splits 0306 bool parentSet = false; 0307 double quantity = 0; 0308 QDomElement splits = operation.firstChildElement(QStringLiteral("SPLITS")); 0309 0310 int nbSuboperations = 0; 0311 suboperationsList.resize(0); 0312 { 0313 QDomNodeList suboperationsListTmp = splits.elementsByTagName(QStringLiteral("SPLIT")); 0314 nbSuboperations = suboperationsListTmp.count(); 0315 0316 for (int j = 0; !err && j < nbSuboperations; ++j) { 0317 QDomElement suboperation = suboperationsListTmp.at(j).toElement(); 0318 if (m_mapIdCategory.contains(suboperation.attribute(QStringLiteral("account")))) { 0319 suboperationsList.push_front(suboperation); 0320 } else { 0321 suboperationsList.push_back(suboperation); 0322 } 0323 } 0324 } 0325 0326 SKGSubOperationObject suboperationObj; 0327 for (int j = 0; !err && j < nbSuboperations; ++j) { 0328 QDomElement suboperation = suboperationsList.at(j).toElement(); 0329 0330 // Set transaction attributes 0331 IFOKDO(err, operationObj.setPayee(mapIdPayee[suboperation.attribute(QStringLiteral("payee"))])) 0332 if (!err && operationObj.getComment().isEmpty()) { 0333 err = operationObj.setComment(suboperation.attribute(QStringLiteral("memo"))); 0334 } 0335 IFOKDO(err, operationObj.setNumber(suboperation.attribute(QStringLiteral("number")))) 0336 0337 // Set state 0338 if (operationObj.getStatus() == SKGOperationObject::NONE) { 0339 QString val = suboperation.attribute(QStringLiteral("reconcileflag")); 0340 IFOKDO(err, operationObj.setStatus(val == QStringLiteral("1") ? SKGOperationObject::MARKED : val == QStringLiteral("2") ? SKGOperationObject::CHECKED : SKGOperationObject::NONE)) 0341 } 0342 IFOKDO(err, operationObj.save()) 0343 0344 if (m_mapIdCategory.contains(suboperation.attribute(QStringLiteral("account")))) { 0345 // It is a split on category 0346 SKGCategoryObject cat = m_mapIdCategory.value(suboperation.attribute(QStringLiteral("account"))); 0347 0348 double q = -toKmyValue(suboperation.attribute(QStringLiteral("shares"))); 0349 if (!err && ((suboperationObj.getID() == 0) || suboperationObj.getQuantity() != q)) { 0350 err = operationObj.addSubOperation(suboperationObj); 0351 } 0352 IFOKDO(err, suboperationObj.setQuantity(q)) 0353 IFOKDO(err, suboperationObj.setCategory(cat)) 0354 IFOKDO(err, suboperationObj.setComment(suboperation.attribute(QStringLiteral("memo")))) 0355 IFOKDO(err, suboperationObj.save(true, false)) 0356 } else { 0357 QString accountSubOp = suboperation.attribute(QStringLiteral("account")); 0358 if (!accountSubOp.isEmpty()) { 0359 if (nbSuboperations == 1) { 0360 SKGUnitObject unit = m_mapIdUnit.value(accountSubOp); 0361 if (unit.getID() != 0) { 0362 IFOKDO(err, operationObj.setUnit(unit)) 0363 } 0364 } 0365 0366 if (!m_mapIdAccount.contains(accountSubOp) || (nbSuboperations == 2 && 0367 m_mapIdAccount.value(accountSubOp) == kmymoneyTemporaryAccount && 0368 suboperationsList.at(0).toElement().attribute(QStringLiteral("action")).isEmpty() && 0369 suboperationsList.at(1).toElement().attribute(QStringLiteral("action")).isEmpty())) { 0370 // Set as initial balance 0371 IFOKDO(err, operationObj.setAttribute(QStringLiteral("d_date"), QStringLiteral("0000-00-00"))) 0372 IFOKDO(err, operationObj.setStatus(SKGOperationObject::CHECKED)) 0373 IFOKDO(err, operationObj.save(true, false)) 0374 0375 if (!err && (suboperationObj.getID() == 0)) { 0376 err = operationObj.addSubOperation(suboperationObj); 0377 } 0378 0379 IFOKDO(err, suboperationObj.setAttribute(QStringLiteral("d_date"), QStringLiteral("0000-00-00"))) 0380 IFOKDO(err, suboperationObj.save(true, false)) 0381 } else { 0382 // It is a transfer of account 0383 SKGAccountObject act = m_mapIdAccount.value(accountSubOp); 0384 0385 if (parentSet) { 0386 // If the parent is already set, it means that is a transfer 0387 SKGOperationObject operationObj2; 0388 IFOKDO(err, act.addOperation(operationObj2, true)) 0389 IFOKDO(err, operationObj2.setTemplate(operationObj.isTemplate())) 0390 IFOKDO(err, operationObj2.setDate(operationObj.getDate())) 0391 IFOKDO(err, operationObj2.setNumber(operationObj.getNumber())) 0392 IFOKDO(err, operationObj2.setComment(operationObj.getComment())) 0393 SKGPayeeObject payeeObject; 0394 operationObj.getPayee(payeeObject); 0395 IFOKDO(err, operationObj2.setPayee(payeeObject)) 0396 IFOK(err) { 0397 QString val = suboperation.attribute(QStringLiteral("reconcileflag")); 0398 err = operationObj2.setStatus(val == QStringLiteral("1") ? SKGOperationObject::MARKED : val == QStringLiteral("2") ? SKGOperationObject::CHECKED : SKGOperationObject::NONE); 0399 } 0400 IFOKDO(err, operationObj2.setImported(true)) 0401 IFOKDO(err, operationObj2.setImportID(operationObj.getImportID())) 0402 0403 SKGUnitObject unit = m_mapIdUnit.value(accountSubOp); 0404 if (unit.getID() != 0) { 0405 IFOKDO(err, operationObj2.setUnit(unit)) 0406 } else { 0407 IFOKDO(err, operationObj.getUnit(unit)) 0408 IFOKDO(err, operationObj2.setUnit(unit)) 0409 } 0410 IFOKDO(err, operationObj2.save()) 0411 IFOKDO(err, operationObj2.setGroupOperation(operationObj)) 0412 IFOKDO(err, operationObj2.save()) 0413 0414 // Create sub transaction on operationObj2 0415 SKGSubOperationObject suboperationObj2; 0416 IFOKDO(err, operationObj2.addSubOperation(suboperationObj2)) 0417 IFOK(err) { 0418 // We must take the quality of the split having an action 0419 quantity = toKmyValue(suboperation.attribute(QStringLiteral("shares"))); 0420 err = suboperationObj2.setQuantity(quantity); 0421 } 0422 IFOKDO(err, suboperationObj2.setComment(suboperation.attribute(QStringLiteral("memo")))) 0423 IFOKDO(err, suboperationObj2.save(true, false)) 0424 } else { 0425 // We set the parent 0426 if (Q_LIKELY(!err) && (act.getID() == 0)) { 0427 err = SKGError(ERR_FAIL, i18nc("Error message", "Account with identifier %1 not found", suboperation.attribute(QStringLiteral("account")))); 0428 } 0429 IFOKDO(err, operationObj.setParentAccount(act, true)) 0430 IFOKDO(err, operationObj.save()) 0431 0432 // Compute quantity 0433 quantity = toKmyValue(suboperation.attribute(QStringLiteral("shares"))); 0434 0435 // Create sub transaction on operationObj 0436 quantity -= SKGServices::stringToDouble(operationObj.getAttribute(QStringLiteral("f_QUANTITY"))); 0437 if (quantity != 0 || nbSuboperations == 1) { 0438 IFOKDO(err, operationObj.addSubOperation(suboperationObj)) 0439 IFOKDO(err, suboperationObj.setQuantity(quantity)) 0440 IFOKDO(err, suboperationObj.setComment(suboperation.attribute(QStringLiteral("memo")))) 0441 IFOKDO(err, suboperationObj.save(true, false)) 0442 } 0443 0444 parentSet = true; 0445 } 0446 } 0447 } 0448 } 0449 } 0450 0451 if (!err && i % 500 == 0) { 0452 err = m_importer->getDocument()->executeSqliteOrder(QStringLiteral("ANALYZE")); 0453 } 0454 0455 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 0456 } 0457 0458 SKGENDTRANSACTION(m_importer->getDocument(), err) 0459 0460 return err; 0461 } 0462 0463 SKGError SKGImportPluginKmy::importBudget(QDomElement& docElem) 0464 { 0465 SKGError err; 0466 QDomElement budgets = docElem.firstChildElement(QStringLiteral("BUDGETS")); 0467 if (!err && !budgets.isNull()) { 0468 SKGTRACEINRC(10, "SKGImportPluginKmy::importFile-BUDGETS", err) 0469 // Build cache of categories 0470 QMap<int, bool> catExpense; 0471 { 0472 SKGStringListList list; 0473 err = m_importer->getDocument()->executeSelectSqliteOrder(QStringLiteral("SELECT id, t_TYPEEXPENSE FROM v_category_display"), list); 0474 int nb = list.count(); 0475 for (int i = 1; i < nb; ++i) { 0476 catExpense[SKGServices::stringToInt(list.at(i).at(0))] = (list.at(i).at(0) == QStringLiteral("-")); 0477 } 0478 } 0479 0480 QDomNodeList budgetList = budgets.elementsByTagName(QStringLiteral("BUDGET")); 0481 int nb = budgetList.count(); 0482 IFOKDO(err, m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import budgets"), nb)) 0483 for (int i = 0; !err && i < nb; ++i) { 0484 QDomElement budget = budgetList.at(i).toElement(); 0485 QDomNodeList accountList = budget.elementsByTagName(QStringLiteral("ACCOUNT")); 0486 int nb2 = accountList.count(); 0487 for (int j = 0; !err && j < nb2; ++j) { 0488 QDomElement account = accountList.at(j).toElement(); 0489 SKGCategoryObject cat = m_mapIdCategory.value(account.attribute(QStringLiteral("id"))); 0490 QString budgetlevel = account.attribute(QStringLiteral("budgetlevel")); 0491 0492 QDomNodeList periodList = account.elementsByTagName(QStringLiteral("PERIOD")); 0493 int nb3 = periodList.count(); 0494 for (int k = 0; !err && k < nb3; ++k) { 0495 QDomElement period = periodList.at(k).toElement(); 0496 0497 double q = toKmyValue(period.attribute(QStringLiteral("amount"))); 0498 0499 // Are we able to find to sign with the category ? 0500 if (catExpense[cat.getID()]) { 0501 q = -q; 0502 } 0503 0504 QStringList dates = SKGServices::splitCSVLine(period.attribute(QStringLiteral("start")), '-'); 0505 if (dates.count() == 3) { 0506 // We try a creation 0507 for (int m = 1; !err && m <= (budgetlevel == QStringLiteral("monthly") ? 12 : 1); ++m) { 0508 SKGBudgetObject budget2(m_importer->getDocument()); 0509 err = budget2.setCategory(cat); 0510 IFOKDO(err, budget2.setBudgetedAmount(q)) 0511 IFOKDO(err, budget2.setYear(SKGServices::stringToDouble(dates.at(0)))) 0512 IFOKDO(err, budget2.setMonth(budgetlevel == QStringLiteral("monthbymonth") ? SKGServices::stringToDouble(dates.at(1)) : 0513 budgetlevel == QStringLiteral("yearly") ? 0 : m)); 0514 IFOKDO(err, budget2.save(true, false)) 0515 } 0516 } 0517 } 0518 } 0519 0520 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 0521 } 0522 0523 SKGENDTRANSACTION(m_importer->getDocument(), err) 0524 } 0525 return err; 0526 } 0527 0528 SKGError SKGImportPluginKmy::importAccounts(SKGBankObject& bank, SKGAccountObject& kmymoneyTemporaryAccount, QMap<QString, SKGBankObject>& mapIdBank, QDomElement& docElem) 0529 { 0530 SKGError err; 0531 IFOKDO(err, m_importer->getDocument()->addOrModifyAccount(QStringLiteral("KMYMONEY-TEMPORARY-ACCOUNT"), QString(), QStringLiteral("KMYMONEY"))) 0532 IFOKDO(err, bank.setName(QStringLiteral("KMYMONEY"))) 0533 IFOKDO(err, bank.load()) 0534 IFOKDO(err, kmymoneyTemporaryAccount.setName(QStringLiteral("KMYMONEY-TEMPORARY-ACCOUNT"))) 0535 IFOKDO(err, kmymoneyTemporaryAccount.load()) 0536 0537 QDomElement accounts = docElem.firstChildElement(QStringLiteral("ACCOUNTS")); 0538 if (!err && !accounts.isNull()) { 0539 SKGTRACEINRC(10, "SKGImportPluginKmy::importFile-ACCOUNTS", err) 0540 QDomNodeList accountList = accounts.elementsByTagName(QStringLiteral("ACCOUNT")); 0541 int nb = accountList.count(); 0542 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import accounts"), nb); 0543 QMap<QString, QString> type15Account; 0544 QMap<QString, QString> type15Unit; 0545 for (int i = 0; !err && i < nb; ++i) { 0546 // Get account object 0547 QDomElement account = accountList.at(i).toElement(); 0548 QString type = account.attribute(QStringLiteral("type")); 0549 if (type == QStringLiteral("15")) { 0550 // Actions: the real account is the parent 0551 type15Account[account.attribute(QStringLiteral("id"))] = account.attribute(QStringLiteral("parentaccount")); 0552 type15Unit[account.attribute(QStringLiteral("id"))] = account.attribute(QStringLiteral("currency")); 0553 } else if (type != QStringLiteral("12") && type != QStringLiteral("13") && type != QStringLiteral("16")) { 0554 // Get the bank 0555 QString bankId = account.attribute(QStringLiteral("institution")); 0556 SKGBankObject bankObj = (bankId.isEmpty() ? bank : mapIdBank[account.attribute(QStringLiteral("institution"))]); 0557 0558 // Creation of the account 0559 SKGAccountObject accountObj; 0560 IFOKDO(err, bankObj.addAccount(accountObj)) 0561 IFOKDO(err, accountObj.setName(account.attribute(QStringLiteral("name")))) 0562 IFOKDO(err, accountObj.setNumber(account.attribute(QStringLiteral("number")))) 0563 IFOKDO(err, accountObj.setComment(account.attribute(QStringLiteral("description")))) 0564 IFOK(err) { 0565 SKGAccountObject::AccountType typeA = (type == QStringLiteral("4") ? SKGAccountObject::CREDITCARD : (type == QStringLiteral("7") ? SKGAccountObject::INVESTMENT : (type == QStringLiteral("9") ? SKGAccountObject::ASSETS : (type == QStringLiteral("3") ? SKGAccountObject::WALLET : (type == QStringLiteral("10") ? SKGAccountObject::LOAN : SKGAccountObject::CURRENT))))); 0566 err = accountObj.setType(typeA); 0567 } 0568 IFOK(err) { 0569 // Set pairs 0570 QDomNodeList pairList = account.elementsByTagName(QStringLiteral("PAIR")); 0571 int nb2 = pairList.count(); 0572 for (int j = 0; !err && j < nb2; ++j) { 0573 QDomElement pair = pairList.at(j).toElement(); 0574 if (pair.attribute(QStringLiteral("key")).toLower() == QStringLiteral("mm-closed") && pair.attribute(QStringLiteral("value")).toLower() == QStringLiteral("yes")) { 0575 err = accountObj.setClosed(true); 0576 } else if (pair.attribute(QStringLiteral("key")).toLower() == QStringLiteral("preferredaccount") && pair.attribute(QStringLiteral("value")).toLower() == QStringLiteral("yes")) { 0577 err = accountObj.bookmark(true); 0578 } else if (pair.attribute(QStringLiteral("key")).toLower() == QStringLiteral("minbalanceabsolute")) { 0579 err = accountObj.setMinLimitAmount(toKmyValue(pair.attribute(QStringLiteral("value")))); 0580 IFOKDO(err, accountObj.minLimitAmountEnabled(true)) 0581 } else if (pair.attribute(QStringLiteral("key")).toLower() == QStringLiteral("maxcreditabsolute")) { 0582 err = accountObj.setMaxLimitAmount(-toKmyValue(pair.attribute(QStringLiteral("value")))); 0583 IFOKDO(err, accountObj.maxLimitAmountEnabled(true)) 0584 } 0585 } 0586 } 0587 IFOKDO(err, accountObj.save()) 0588 0589 // Change parent bank in case of ASSETS 0590 if (accountObj.getType() == SKGAccountObject::WALLET) { 0591 // Get blank bank 0592 SKGBankObject blankBank(m_importer->getDocument()); 0593 IFOKDO(err, blankBank.setName(QString())) 0594 if (blankBank.exist()) { 0595 err = blankBank.load(); 0596 } else { 0597 err = blankBank.save(); 0598 } 0599 IFOKDO(err, accountObj.setBank(blankBank)) 0600 IFOKDO(err, accountObj.save()) 0601 } 0602 0603 m_mapIdAccount[account.attribute(QStringLiteral("id"))] = accountObj; 0604 } else if (type == QStringLiteral("16")) { 0605 m_mapIdAccount[account.attribute(QStringLiteral("id"))] = kmymoneyTemporaryAccount; 0606 } else { 0607 // Create category 0608 SKGCategoryObject cat = m_mapIdCategory.value(account.attribute(QStringLiteral("id"))); 0609 if (cat.getID() != 0) { 0610 // Already existing ==> we must set the right name 0611 err = cat.setName(account.attribute(QStringLiteral("name"))); 0612 IFOKDO(err, cat.save()) 0613 } else { 0614 // We must create it 0615 cat = SKGCategoryObject(m_importer->getDocument()); 0616 err = cat.setName(account.attribute(QStringLiteral("name"))); 0617 IFOKDO(err, cat.save()) 0618 } 0619 if (err) { 0620 // The category already exists 0621 SKGCategoryObject catp; 0622 err = cat.getParentCategory(catp); 0623 QString fullName = catp.getFullName() % OBJECTSEPARATOR % cat.getName(); 0624 IFOKDO(err, cat.remove(false)) 0625 IFOKDO(err, SKGCategoryObject::createPathCategory(m_importer->getDocument(), fullName, cat)) 0626 } 0627 m_mapIdCategory[account.attribute(QStringLiteral("id"))] = cat; 0628 0629 // Create sub categories 0630 QDomNodeList subaccountList = account.elementsByTagName(QStringLiteral("SUBACCOUNT")); 0631 int nb2 = subaccountList.count(); 0632 for (int j = 0; !err && j < nb2; ++j) { 0633 QDomElement subaccount = subaccountList.at(j).toElement(); 0634 0635 // Is child already existing ? 0636 SKGCategoryObject cat2 = m_mapIdCategory.value(subaccount.attribute(QStringLiteral("id"))); 0637 if (cat2.getID() != 0) { 0638 // Yes ==> reparent 0639 err = cat2.setParentCategory(cat); 0640 IFOKDO(err, cat2.save(true, false)) 0641 } else { 0642 // No ==> create 0643 IFOKDO(err, cat.addCategory(cat2)) 0644 IFOKDO(err, cat2.setName(subaccount.attribute(QStringLiteral("id")))) 0645 IFOKDO(err, cat2.save()) 0646 m_mapIdCategory[subaccount.attribute(QStringLiteral("id"))] = cat2; 0647 } 0648 } 0649 } 0650 0651 QStringList list = type15Account.keys(); 0652 for (const auto& k : qAsConst(list)) { 0653 m_mapIdAccount[k] = m_mapIdAccount.value(type15Account[k]); 0654 m_mapIdUnit[account.attribute(QStringLiteral("id"))] = m_mapIdUnit.value(account.attribute(QStringLiteral("currency"))); 0655 } 0656 0657 list = type15Unit.keys(); 0658 for (const auto& k : qAsConst(list)) { 0659 m_mapIdUnit[k] = m_mapIdUnit[type15Unit[k]]; 0660 } 0661 0662 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 0663 } 0664 0665 SKGENDTRANSACTION(m_importer->getDocument(), err) 0666 } 0667 return err; 0668 } 0669 0670 SKGError SKGImportPluginKmy::importFile() 0671 { 0672 if (m_importer->getDocument() == nullptr) { 0673 return SKGError(ERR_ABORT, i18nc("Error message", "Invalid parameters")); 0674 } 0675 0676 SKGError err; 0677 SKGTRACEINFUNCRC(2, err) 0678 0679 // Initialisation 0680 m_mapIdUnit.clear(); 0681 m_mapIdAccount.clear(); 0682 m_mapIdCategory.clear(); 0683 m_mapIdPayee.clear(); 0684 0685 // Open file 0686 KCompressionDevice file(m_importer->getLocalFileName(), KCompressionDevice::GZip); 0687 if (!file.open(QIODevice::ReadOnly)) { 0688 err.setReturnCode(ERR_INVALIDARG).setMessage(i18nc("Error message", "Open file '%1' failed", m_importer->getFileName().toDisplayString())); 0689 } else { 0690 QDomDocument doc; 0691 0692 // Set the file without uncompression 0693 QString errorMsg; 0694 int errorLine = 0; 0695 int errorCol = 0; 0696 bool contentOK = doc.setContent(file.readAll(), &errorMsg, &errorLine, &errorCol); 0697 file.close(); 0698 0699 if (!contentOK) { 0700 err.setReturnCode(ERR_ABORT).setMessage(i18nc("Error message", "%1-%2: '%3'", errorLine, errorCol, errorMsg)).addError(ERR_INVALIDARG, i18nc("Error message", "Invalid XML content in file '%1'", m_importer->getFileName().toDisplayString())); 0701 } else { 0702 // Get root 0703 QDomElement docElem = doc.documentElement(); 0704 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import %1 file", "KMY"), 8); 0705 0706 // Step 1-Get units 0707 IFOKDO(err, importSecurities(docElem)) 0708 IFOKDO(err, m_importer->getDocument()->stepForward(1)) 0709 0710 // Step 2-Get units prices 0711 IFOKDO(err, importPrices(docElem)) 0712 IFOKDO(err, m_importer->getDocument()->stepForward(2)) 0713 0714 // Step 3-Create banks 0715 QMap<QString, SKGBankObject> mapIdBank; 0716 IFOKDO(err, importInstitutions(mapIdBank, docElem)) 0717 IFOKDO(err, m_importer->getDocument()->stepForward(3)) 0718 0719 // Step 4-Create account and categories 0720 // Create bank and temporary account for kmymoney import 0721 SKGAccountObject kmymoneyTemporaryAccount(m_importer->getDocument()); 0722 SKGBankObject bank(m_importer->getDocument()); 0723 IFOKDO(err, importAccounts(bank, kmymoneyTemporaryAccount, mapIdBank, docElem)) 0724 IFOKDO(err, m_importer->getDocument()->stepForward(4)) 0725 0726 // Step 5-Read payees 0727 QMap<QString, SKGPayeeObject> mapIdPayee; 0728 IFOKDO(err, importPayees(mapIdPayee, docElem)) 0729 IFOKDO(err, m_importer->getDocument()->stepForward(5)) 0730 0731 // Step 6-Create transactions 0732 IFOKDO(err, importTransactions(docElem, kmymoneyTemporaryAccount, mapIdPayee)) 0733 IFOKDO(err, m_importer->getDocument()->stepForward(6)) 0734 0735 // Step 7-Get budgets 0736 IFOKDO(err, importBudget(docElem)) 0737 IFOKDO(err, m_importer->getDocument()->stepForward(7)) 0738 0739 // Step 8-Remove useless account and temporary account 0740 { 0741 IFOKDO(err, kmymoneyTemporaryAccount.remove(false, true)) 0742 IFOKDO(err, m_importer->getDocument()->executeSqliteOrder("DELETE FROM account WHERE rd_bank_id=" % SKGServices::intToString(bank.getID()) % " AND (SELECT COUNT(1) FROM operation WHERE operation.rd_account_id=account.id)=0")) 0743 } 0744 IFOKDO(err, m_importer->getDocument()->stepForward(8)) 0745 0746 SKGENDTRANSACTION(m_importer->getDocument(), err) 0747 0748 IFOKDO(err, m_importer->getDocument()->executeSqliteOrder(QStringLiteral("ANALYZE"))) 0749 } 0750 } 0751 0752 // Clean 0753 m_mapIdUnit.clear(); 0754 m_mapIdAccount.clear(); 0755 m_mapIdCategory.clear(); 0756 m_mapIdPayee.clear(); 0757 0758 return err; 0759 } 0760 0761 bool SKGImportPluginKmy::isExportPossible() 0762 { 0763 SKGTRACEINFUNC(10) 0764 return (m_importer->getDocument() == nullptr ? true : m_importer->getFileNameExtension() == QStringLiteral("KMY")); 0765 } 0766 0767 SKGError SKGImportPluginKmy::exportHeader(QDomDocument& doc, QDomElement& root) 0768 { 0769 SKGError err; 0770 QDomElement fileindo = doc.createElement(QStringLiteral("FILEINFO")); 0771 root.appendChild(fileindo); 0772 0773 { 0774 // <CREATION_DATE> 0775 QDomElement creation_date = doc.createElement(QStringLiteral("CREATION_DATE")); 0776 fileindo.appendChild(creation_date); 0777 creation_date.setAttribute(QStringLiteral("date"), SKGServices::dateToSqlString(QDateTime::currentDateTime())); 0778 0779 // <LAST_MODIFIED_DATE> 0780 QDomElement last_modified_date = doc.createElement(QStringLiteral("LAST_MODIFIED_DATE")); 0781 fileindo.appendChild(last_modified_date); 0782 last_modified_date.setAttribute(QStringLiteral("date"), SKGServices::dateToSqlString(QDateTime::currentDateTime())); 0783 0784 // <VERSION> 0785 QDomElement version = doc.createElement(QStringLiteral("VERSION")); 0786 fileindo.appendChild(version); 0787 version.setAttribute(QStringLiteral("id"), QStringLiteral("1")); 0788 0789 // <FIXVERSION> 0790 QDomElement fixversion = doc.createElement(QStringLiteral("FIXVERSION")); 0791 fileindo.appendChild(fixversion); 0792 fixversion.setAttribute(QStringLiteral("id"), QStringLiteral("2")); 0793 } 0794 0795 // <USER> 0796 QDomElement user = doc.createElement(QStringLiteral("USER")); 0797 root.appendChild(user); 0798 user.setAttribute(QStringLiteral("email"), QString()); 0799 user.setAttribute(QStringLiteral("name"), QString()); 0800 { 0801 // ADDRESS 0802 QDomElement address = doc.createElement(QStringLiteral("ADDRESS")); 0803 user.appendChild(address); 0804 address.setAttribute(QStringLiteral("street"), QString()); 0805 address.setAttribute(QStringLiteral("zipcode"), QString()); 0806 address.setAttribute(QStringLiteral("county"), QString()); 0807 address.setAttribute(QStringLiteral("city"), QString()); 0808 address.setAttribute(QStringLiteral("telephone"), QString()); 0809 } 0810 return err; 0811 } 0812 0813 SKGError SKGImportPluginKmy::exportSecurities(QDomDocument& doc, QDomElement& root, const QString& stdUnit) 0814 { 0815 SKGError err; 0816 QDomElement securities = doc.createElement(QStringLiteral("SECURITIES")); 0817 root.appendChild(securities); 0818 0819 QDomElement currencies = doc.createElement(QStringLiteral("CURRENCIES")); 0820 root.appendChild(currencies); 0821 0822 SKGObjectBase::SKGListSKGObjectBase objects; 0823 IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_unit"), QStringLiteral("t_type!='I'"), objects)) 0824 int nb = objects.count(); 0825 securities.setAttribute(QStringLiteral("count"), SKGServices::intToString(nb)); 0826 0827 QStringList importedCurrency; 0828 IFOK(err) { 0829 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export units"), nb); 0830 for (int i = 0; !err && i < nb; ++i) { 0831 SKGUnitObject obj(objects.at(i)); 0832 if (obj.getType() == SKGUnitObject::SHARE || obj.getType() == SKGUnitObject::OBJECT) { 0833 QDomElement security = doc.createElement(QStringLiteral("SECURITY")); 0834 securities.appendChild(security); 0835 0836 SKGUnitObject parentUnit; 0837 obj.getUnit(parentUnit); 0838 QString unitP = SKGUnitObject::getInternationalCode(parentUnit.getName()); 0839 if (unitP.isEmpty()) { 0840 unitP = stdUnit; 0841 } 0842 0843 security.setAttribute(QStringLiteral("id"), obj.getName()); 0844 security.setAttribute(QStringLiteral("trading-currency"), unitP); 0845 security.setAttribute(QStringLiteral("saf"), QStringLiteral("100000")); 0846 security.setAttribute(QStringLiteral("symbol"), obj.getSymbol()); 0847 security.setAttribute(QStringLiteral("trading-market"), obj.getCountry()); 0848 security.setAttribute(QStringLiteral("type"), QStringLiteral("4")); 0849 security.setAttribute(QStringLiteral("name"), obj.getName()); 0850 0851 QString internetCode = obj.getInternetCode(); 0852 if (!internetCode.isEmpty()) { 0853 QDomElement keyvaluepairs2 = doc.createElement(QStringLiteral("KEYVALUEPAIRS")); 0854 security.appendChild(keyvaluepairs2); 0855 0856 QDomElement pair1 = doc.createElement(QStringLiteral("PAIR")); 0857 keyvaluepairs2.appendChild(pair1); 0858 pair1.setAttribute(QStringLiteral("key"), QStringLiteral("kmm-online-source")); 0859 pair1.setAttribute(QStringLiteral("value"), QStringLiteral("Yahoo")); 0860 0861 QDomElement pair2 = doc.createElement(QStringLiteral("PAIR")); 0862 keyvaluepairs2.appendChild(pair2); 0863 pair2.setAttribute(QStringLiteral("key"), QStringLiteral("kmm-security-id")); 0864 pair2.setAttribute(QStringLiteral("value"), internetCode); 0865 } 0866 } else { 0867 QDomElement currency = doc.createElement(QStringLiteral("CURRENCY")); 0868 currencies.appendChild(currency); 0869 0870 QString unit = SKGUnitObject::getInternationalCode(obj.getName()); 0871 if (unit.isEmpty()) { 0872 unit = obj.getName(); 0873 } 0874 0875 currency.setAttribute(QStringLiteral("saf"), QStringLiteral("100")); 0876 currency.setAttribute(QStringLiteral("symbol"), obj.getSymbol()); 0877 currency.setAttribute(QStringLiteral("type"), QStringLiteral("3")); 0878 currency.setAttribute(QStringLiteral("id"), unit); 0879 currency.setAttribute(QStringLiteral("name"), obj.getName()); 0880 currency.setAttribute(QStringLiteral("ppu"), QStringLiteral("100")); 0881 currency.setAttribute(QStringLiteral("scf"), QStringLiteral("100")); 0882 0883 importedCurrency.push_back(obj.getSymbol()); 0884 } 0885 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 0886 } 0887 0888 SKGENDTRANSACTION(m_importer->getDocument(), err) 0889 } 0890 0891 // <CURRENCIES> 0892 QStringList units = SKGUnitObject::getListofKnownCurrencies(false); 0893 nb = units.count(); 0894 int nbreal = 0; 0895 for (int i = 0; i < nb; ++i) { 0896 SKGServices::SKGUnitInfo info = SKGUnitObject::getUnitInfo(units.at(i)); 0897 if (info.Name != info.Symbol && !importedCurrency.contains(info.Symbol)) { 0898 QDomElement currency = doc.createElement(QStringLiteral("CURRENCY")); 0899 currencies.appendChild(currency); 0900 currency.setAttribute(QStringLiteral("saf"), QStringLiteral("100")); 0901 currency.setAttribute(QStringLiteral("symbol"), info.Symbol); 0902 currency.setAttribute(QStringLiteral("type"), QStringLiteral("3")); 0903 currency.setAttribute(QStringLiteral("id"), SKGUnitObject::getInternationalCode(info.Name)); 0904 currency.setAttribute(QStringLiteral("name"), info.Name); 0905 currency.setAttribute(QStringLiteral("ppu"), QStringLiteral("100")); 0906 currency.setAttribute(QStringLiteral("scf"), QStringLiteral("100")); 0907 0908 ++nbreal; 0909 } 0910 } 0911 currencies.setAttribute(QStringLiteral("count"), SKGServices::intToString(nbreal)); 0912 0913 // <PRICES> 0914 QDomElement prices = doc.createElement(QStringLiteral("PRICES")); 0915 root.appendChild(prices); 0916 IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_unit"), QStringLiteral("t_type='S'"), objects)) 0917 nb = objects.count(); 0918 prices.setAttribute(QStringLiteral("count"), SKGServices::intToString(nb)); 0919 IFOK(err) { 0920 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export units"), nb); 0921 for (int i = 0; !err && i < nb; ++i) { 0922 SKGUnitObject obj(objects.at(i)); 0923 QDomElement pricepair = doc.createElement(QStringLiteral("PRICEPAIR")); 0924 prices.appendChild(pricepair); 0925 0926 QString unitP = SKGUnitObject::getInternationalCode(obj.getName()); 0927 if (unitP.isEmpty()) { 0928 unitP = stdUnit; 0929 } 0930 0931 pricepair.setAttribute(QStringLiteral("from"), obj.getName()); 0932 pricepair.setAttribute(QStringLiteral("to"), unitP); 0933 0934 SKGObjectBase::SKGListSKGObjectBase unitValues; 0935 err = obj.getUnitValues(unitValues); 0936 int nb2 = unitValues.count(); 0937 for (int j = 0; !err && j < nb2; ++j) { 0938 QDomElement price = doc.createElement(QStringLiteral("PRICE")); 0939 pricepair.appendChild(price); 0940 0941 SKGUnitValueObject unitval(unitValues.at(j)); 0942 price.setAttribute(QStringLiteral("price"), SKGImportPluginKmy::kmyValue(unitval.getQuantity())); 0943 price.setAttribute(QStringLiteral("source"), QStringLiteral("Utilisateur")); 0944 price.setAttribute(QStringLiteral("date"), SKGServices::dateToSqlString(unitval.getDate())); 0945 } 0946 0947 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 0948 } 0949 0950 SKGENDTRANSACTION(m_importer->getDocument(), err) 0951 } 0952 0953 // <REPORTS> 0954 QDomElement reports = doc.createElement(QStringLiteral("REPORTS")); 0955 root.appendChild(reports); 0956 reports.setAttribute(QStringLiteral("count"), QStringLiteral("0")); 0957 0958 return err; 0959 } 0960 0961 SKGError SKGImportPluginKmy::exportBudgets(QDomDocument& doc, QDomElement& root) 0962 { 0963 SKGError err; 0964 QDomElement budgets = doc.createElement(QStringLiteral("BUDGETS")); 0965 root.appendChild(budgets); 0966 0967 SKGObjectBase::SKGListSKGObjectBase objects; 0968 IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_budget"), QStringLiteral("1=1 ORDER BY i_year, i_month"), objects)) 0969 int nb = objects.count(); 0970 int nbBudgets = 0; 0971 int currentYear = 0; 0972 QDomElement budget; 0973 0974 QMap<QString, QDomElement> mapCatAccount; 0975 IFOK(err) { 0976 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export budgets"), nb); 0977 for (int i = 0; !err && i < nb; ++i) { 0978 SKGBudgetObject obj(objects.at(i)); 0979 SKGCategoryObject cat; 0980 obj.getCategory(cat); 0981 QString catId = getKmyUniqueIdentifier(cat); 0982 int year = obj.getYear(); 0983 QString yearString = SKGServices::intToString(year); 0984 int month = obj.getMonth(); 0985 QString monthString = SKGServices::intToString(month); 0986 if (monthString.isEmpty()) { 0987 monthString = '0' % monthString; 0988 } 0989 if (currentYear != year) { 0990 budget = doc.createElement(QStringLiteral("BUDGET")); 0991 budgets.appendChild(budget); 0992 budget.setAttribute(QStringLiteral("version"), QStringLiteral("2")); 0993 budget.setAttribute(QStringLiteral("id"), yearString); 0994 budget.setAttribute(QStringLiteral("start"), yearString % "-01-01"); 0995 budget.setAttribute(QStringLiteral("name"), yearString); 0996 0997 currentYear = year; 0998 mapCatAccount.clear(); 0999 ++nbBudgets; 1000 } 1001 1002 QDomElement account = mapCatAccount[catId]; 1003 if (account.isNull() && !catId.isEmpty()) { 1004 account = doc.createElement(QStringLiteral("ACCOUNT")); 1005 budget.appendChild(account); 1006 account.setAttribute(QStringLiteral("budgetsubaccounts"), QStringLiteral("0")); 1007 account.setAttribute(QStringLiteral("id"), catId); 1008 mapCatAccount[catId] = account; 1009 } 1010 if (!account.isNull()) { 1011 account.setAttribute(QStringLiteral("budgetlevel"), obj.getMonth() == 0 ? QStringLiteral("yearly") : QStringLiteral("monthbymonth")); 1012 1013 QDomElement period = doc.createElement(QStringLiteral("PERIOD")); 1014 account.appendChild(period); 1015 period.setAttribute(QStringLiteral("amount"), SKGImportPluginKmy::kmyValue(qAbs(obj.getBudgetedAmount()))); 1016 period.setAttribute(QStringLiteral("start"), yearString % '-' % (obj.getMonth() == 0 ? QStringLiteral("01") : monthString) % "-01"); 1017 } 1018 1019 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 1020 } 1021 1022 SKGENDTRANSACTION(m_importer->getDocument(), err) 1023 } 1024 budgets.setAttribute(QStringLiteral("count"), SKGServices::intToString(nbBudgets)); 1025 return err; 1026 } 1027 1028 SKGError SKGImportPluginKmy::exportSchedules(QDomDocument& doc, QDomElement& root) 1029 { 1030 SKGError err; 1031 QDomElement schedules = doc.createElement(QStringLiteral("SCHEDULES")); 1032 root.appendChild(schedules); 1033 1034 SKGObjectBase::SKGListSKGObjectBase objects; 1035 IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_recurrentoperation"), QString(), objects)) 1036 int nb = objects.count(); 1037 schedules.setAttribute(QStringLiteral("count"), SKGServices::intToString(nb)); 1038 IFOK(err) { 1039 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export scheduled transactions"), nb); 1040 for (int i = 0; !err && i < nb; ++i) { 1041 SKGRecurrentOperationObject obj(objects.at(i)); 1042 SKGOperationObject op; 1043 err = obj.getParentOperation(op); 1044 IFOK(err) { 1045 QDomElement scheduled_tx = doc.createElement(QStringLiteral("SCHEDULED_TX")); 1046 schedules.appendChild(scheduled_tx); 1047 1048 scheduled_tx.setAttribute(QStringLiteral("id"), getKmyUniqueIdentifier(obj)); 1049 scheduled_tx.setAttribute(QStringLiteral("name"), getKmyUniqueIdentifier(obj)); 1050 scheduled_tx.setAttribute(QStringLiteral("startDate"), obj.getAttribute(QStringLiteral("d_date"))); 1051 scheduled_tx.setAttribute(QStringLiteral("lastPayment"), obj.getAttribute(QStringLiteral("d_date"))); 1052 bool autoEnter = obj.isAutoWriteEnabled(); 1053 scheduled_tx.setAttribute(QStringLiteral("autoEnter"), autoEnter ? QStringLiteral("1") : QStringLiteral("0")); 1054 1055 QString occuType; 1056 int occu = obj.getPeriodIncrement(); 1057 SKGRecurrentOperationObject::PeriodUnit punit = obj.getPeriodUnit(); 1058 if (punit == SKGRecurrentOperationObject::MONTH) { 1059 occuType = QStringLiteral("32"); 1060 } else if (punit == SKGRecurrentOperationObject::WEEK) { 1061 occuType = '4'; 1062 } else if (punit == SKGRecurrentOperationObject::DAY) { 1063 occuType = '2'; 1064 } else { 1065 occuType = QStringLiteral("16384"); 1066 } 1067 1068 scheduled_tx.setAttribute(QStringLiteral("occurenceMultiplier"), SKGServices::intToString(occu)); 1069 scheduled_tx.setAttribute(QStringLiteral("occurence"), occuType); // krazy:exclude=spelling 1070 scheduled_tx.setAttribute(QStringLiteral("weekendOption"), QStringLiteral("0")); 1071 scheduled_tx.setAttribute(QStringLiteral("paymentType"), QStringLiteral("1")); 1072 QChar type = '1'; 1073 SKGOperationObject op2; 1074 if (op.isTransfer(op2)) { 1075 type = '4'; 1076 } else if (op.getCurrentAmount() > 0) { 1077 type = '2'; 1078 } 1079 scheduled_tx.setAttribute(QStringLiteral("type"), type); 1080 scheduled_tx.setAttribute(QStringLiteral("fixed"), QStringLiteral("1")); 1081 1082 QString endDate; 1083 if (obj.hasTimeLimit()) { 1084 QDate firstDate = obj.getDate(); 1085 1086 // We must compute the date 1087 int p = occu * (obj.getTimeLimit() - 1); 1088 if (punit == SKGRecurrentOperationObject::DAY) { 1089 firstDate = firstDate.addDays(p); 1090 } else if (punit == SKGRecurrentOperationObject::MONTH) { 1091 firstDate = firstDate.addMonths(p); 1092 } else if (punit == SKGRecurrentOperationObject::YEAR) { 1093 firstDate = firstDate.addYears(p); 1094 } 1095 1096 endDate = firstDate.toString(QStringLiteral("yyyy-MM-dd")); 1097 } 1098 scheduled_tx.setAttribute(QStringLiteral("endDate"), endDate); 1099 1100 err = exportOperation(op, doc, scheduled_tx); 1101 } 1102 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 1103 } 1104 1105 SKGENDTRANSACTION(m_importer->getDocument(), err) 1106 } 1107 return err; 1108 } 1109 1110 SKGError SKGImportPluginKmy::exportTransactions(QDomDocument& doc, QDomElement& root, const QString& stdUnit) 1111 { 1112 SKGError err; 1113 QDomElement transactions = doc.createElement(QStringLiteral("TRANSACTIONS")); 1114 root.appendChild(transactions); 1115 1116 SKGObjectBase::SKGListSKGObjectBase objects; 1117 IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_operation"), QStringLiteral("t_template='N' ORDER BY d_date DESC"), objects)) 1118 int nb = objects.count(); 1119 transactions.setAttribute(QStringLiteral("count"), SKGServices::intToString(nb)); 1120 IFOK(err) { 1121 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export transactions"), nb); 1122 for (int i = 0; !err && i < nb; ++i) { 1123 SKGOperationObject op(objects.at(i)); 1124 err = exportOperation(op, doc, transactions); 1125 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 1126 } 1127 1128 SKGENDTRANSACTION(m_importer->getDocument(), err) 1129 } 1130 1131 // <KEYVALUEPAIRS> 1132 QDomElement keyvaluepairs = doc.createElement(QStringLiteral("KEYVALUEPAIRS")); 1133 root.appendChild(keyvaluepairs); 1134 { 1135 QDomElement pair = doc.createElement(QStringLiteral("PAIR")); 1136 keyvaluepairs.appendChild(pair); 1137 pair.setAttribute(QStringLiteral("key"), QStringLiteral("kmm-baseCurrency")); 1138 pair.setAttribute(QStringLiteral("value"), stdUnit); 1139 } 1140 return err; 1141 } 1142 1143 SKGError SKGImportPluginKmy::exportPayees(QDomDocument& doc, QDomElement& root) 1144 { 1145 SKGError err; 1146 QDomElement payees = doc.createElement(QStringLiteral("PAYEES")); 1147 root.appendChild(payees); 1148 1149 SKGObjectBase::SKGListSKGObjectBase listPayees; 1150 IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_payee"), QString(), listPayees)) 1151 int nb = listPayees.count(); 1152 payees.setAttribute(QStringLiteral("count"), SKGServices::intToString(nb)); 1153 IFOK(err) { 1154 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export payees"), nb); 1155 for (int i = 0; !err && i < nb; ++i) { 1156 SKGPayeeObject payeeObject(listPayees.at(i)); 1157 QDomElement payee = doc.createElement(QStringLiteral("PAYEE")); 1158 payees.appendChild(payee); 1159 1160 payee.setAttribute(QStringLiteral("matchingenabled"), QStringLiteral("0")); 1161 payee.setAttribute(QStringLiteral("id"), getKmyUniqueIdentifier(payeeObject)); 1162 payee.setAttribute(QStringLiteral("name"), payeeObject.getName()); 1163 payee.setAttribute(QStringLiteral("email"), QString()); 1164 payee.setAttribute(QStringLiteral("reference"), QString()); 1165 1166 QDomElement address = doc.createElement(QStringLiteral("ADDRESS")); 1167 payee.appendChild(address); 1168 1169 address.setAttribute(QStringLiteral("street"), payeeObject.getAddress()); 1170 address.setAttribute(QStringLiteral("postcode"), QString()); 1171 address.setAttribute(QStringLiteral("zip"), QString()); 1172 address.setAttribute(QStringLiteral("city"), QString()); 1173 address.setAttribute(QStringLiteral("telephone"), QString()); 1174 address.setAttribute(QStringLiteral("state"), QString()); 1175 1176 m_mapIdPayee[SKGServices::intToString(i + 1)] = payeeObject; 1177 1178 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 1179 } 1180 1181 SKGENDTRANSACTION(m_importer->getDocument(), err) 1182 } 1183 return err; 1184 } 1185 1186 SKGError SKGImportPluginKmy::exportInstitutions(QDomDocument& doc, QDomElement& root) 1187 { 1188 SKGError err; 1189 QDomElement institutions = doc.createElement(QStringLiteral("INSTITUTIONS")); 1190 root.appendChild(institutions); 1191 SKGObjectBase::SKGListSKGObjectBase objects; 1192 IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_bank"), QStringLiteral("EXISTS(SELECT 1 FROM account WHERE account.rd_bank_id=v_bank.id)"), objects)) 1193 int nb = objects.count(); 1194 institutions.setAttribute(QStringLiteral("count"), SKGServices::intToString(nb)); 1195 IFOK(err) { 1196 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export banks"), nb); 1197 for (int i = 0; !err && i < nb; ++i) { 1198 SKGBankObject obj(objects.at(i)); 1199 QDomElement institution = doc.createElement(QStringLiteral("INSTITUTION")); 1200 institutions.appendChild(institution); 1201 1202 institution.setAttribute(QStringLiteral("id"), getKmyUniqueIdentifier(obj)); 1203 institution.setAttribute(QStringLiteral("name"), obj.getName()); 1204 institution.setAttribute(QStringLiteral("sortcode"), obj.getNumber()); 1205 institution.setAttribute(QStringLiteral("manager"), QString()); 1206 1207 QDomElement address = doc.createElement(QStringLiteral("ADDRESS")); 1208 institution.appendChild(address); 1209 1210 address.setAttribute(QStringLiteral("street"), QString()); 1211 address.setAttribute(QStringLiteral("zip"), QString()); 1212 address.setAttribute(QStringLiteral("city"), QString()); 1213 address.setAttribute(QStringLiteral("telephone"), QString()); 1214 1215 QDomElement accountids = doc.createElement(QStringLiteral("ACCOUNTIDS")); 1216 institution.appendChild(accountids); 1217 1218 SKGObjectBase::SKGListSKGObjectBase accounts; 1219 err = obj.getAccounts(accounts); 1220 int nb2 = accounts.count(); 1221 for (int j = 0; !err && j < nb2; ++j) { 1222 QDomElement accountid = doc.createElement(QStringLiteral("ACCOUNTID")); 1223 accountids.appendChild(accountid); 1224 1225 accountid.setAttribute(QStringLiteral("id"), getKmyUniqueIdentifier(accounts.at(j))); 1226 } 1227 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 1228 } 1229 1230 SKGENDTRANSACTION(m_importer->getDocument(), err) 1231 } 1232 1233 return err; 1234 } 1235 1236 SKGError SKGImportPluginKmy::exportCategories(QDomDocument& doc, QDomElement& accounts, const QString& stdUnit, QDomElement& accountIncome, QDomElement& accountExpense, int nbAccount) 1237 { 1238 // The v_category_display are retrieved to improve performances of getCurrentAmount 1239 SKGError err; 1240 SKGObjectBase::SKGListSKGObjectBase objects; 1241 IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_category_display"), QString(), objects)) 1242 accounts.setAttribute(QStringLiteral("count"), SKGServices::intToString(5 + nbAccount + objects.count())); 1243 int nb = objects.count(); 1244 IFOK(err) { 1245 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export categories"), nb); 1246 for (int i = 0; !err && i < nb; ++i) { 1247 SKGCategoryObject obj(objects.at(i)); 1248 QDomElement account = doc.createElement(QStringLiteral("ACCOUNT")); 1249 accounts.appendChild(account); 1250 1251 account.setAttribute(QStringLiteral("id"), getKmyUniqueIdentifier(obj)); 1252 account.setAttribute(QStringLiteral("name"), obj.getName()); 1253 account.setAttribute(QStringLiteral("number"), QString()); 1254 account.setAttribute(QStringLiteral("type"), obj.getCurrentAmount() < 0 ? QStringLiteral("13") : QStringLiteral("12")); 1255 1256 account.setAttribute(QStringLiteral("institution"), QString()); 1257 1258 SKGCategoryObject parentCat; 1259 obj.getParentCategory(parentCat); 1260 1261 QString parentId = (parentCat.getID() != 0 ? getKmyUniqueIdentifier(parentCat) : (obj.getCurrentAmount() < 0 ? QStringLiteral("AStd::Expense") : QStringLiteral("AStd::Income"))); 1262 if (parentId == QStringLiteral("AStd::Expense")) { 1263 QDomElement subaccount = doc.createElement(QStringLiteral("SUBACCOUNT")); 1264 accountExpense.appendChild(subaccount); 1265 subaccount.setAttribute(QStringLiteral("id"), getKmyUniqueIdentifier(obj)); 1266 } else if (parentId == QStringLiteral("AStd::Income")) { 1267 QDomElement subaccount = doc.createElement(QStringLiteral("SUBACCOUNT")); 1268 accountIncome.appendChild(subaccount); 1269 subaccount.setAttribute(QStringLiteral("id"), getKmyUniqueIdentifier(obj)); 1270 } 1271 1272 account.setAttribute(QStringLiteral("parentaccount"), parentId); 1273 account.setAttribute(QStringLiteral("lastmodified"), QString()); 1274 account.setAttribute(QStringLiteral("lastreconciled"), QString()); 1275 account.setAttribute(QStringLiteral("opened"), QString()); 1276 account.setAttribute(QStringLiteral("currency"), stdUnit); 1277 account.setAttribute(QStringLiteral("description"), QString()); 1278 1279 QDomElement subaccounts = doc.createElement(QStringLiteral("SUBACCOUNTS")); 1280 account.appendChild(subaccounts); 1281 1282 SKGObjectBase::SKGListSKGObjectBase categories; 1283 IFOKDO(err, obj.getCategories(categories)) 1284 int nb2 = categories.count(); 1285 for (int j = 0; !err && j < nb2; ++j) { 1286 QDomElement subaccount = doc.createElement(QStringLiteral("SUBACCOUNT")); 1287 subaccounts.appendChild(subaccount); 1288 1289 subaccount.setAttribute(QStringLiteral("id"), getKmyUniqueIdentifier(categories.at(j))); 1290 } 1291 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 1292 } 1293 1294 SKGENDTRANSACTION(m_importer->getDocument(), err) 1295 } 1296 return err; 1297 } 1298 1299 SKGError SKGImportPluginKmy::exportAccounts(QDomDocument& doc, QDomElement& root, const QString& stdUnit, QDomElement& accounts, QDomElement& accountIncome, QDomElement& accountExpense, int& nbAccounts) 1300 { 1301 SKGError err; 1302 accounts = doc.createElement(QStringLiteral("ACCOUNTS")); 1303 root.appendChild(accounts); 1304 1305 QDomElement accountAsset; 1306 { 1307 QDomElement account = doc.createElement(QStringLiteral("ACCOUNT")); 1308 accounts.appendChild(account); 1309 1310 account.setAttribute(QStringLiteral("id"), QStringLiteral("AStd::Equity")); 1311 account.setAttribute(QStringLiteral("name"), QStringLiteral("Equity")); 1312 account.setAttribute(QStringLiteral("number"), QString()); 1313 account.setAttribute(QStringLiteral("type"), QStringLiteral("16")); 1314 account.setAttribute(QStringLiteral("institution"), QString()); 1315 account.setAttribute(QStringLiteral("parentaccount"), QString()); 1316 account.setAttribute(QStringLiteral("lastmodified"), QString()); 1317 account.setAttribute(QStringLiteral("lastreconciled"), QString()); 1318 account.setAttribute(QStringLiteral("opened"), QString()); 1319 account.setAttribute(QStringLiteral("currency"), stdUnit); 1320 account.setAttribute(QStringLiteral("description"), QString()); 1321 1322 QDomElement subaccounts = doc.createElement(QStringLiteral("SUBACCOUNTS")); 1323 account.appendChild(subaccounts); 1324 } 1325 1326 { 1327 QDomElement account = doc.createElement(QStringLiteral("ACCOUNT")); 1328 accounts.appendChild(account); 1329 1330 account.setAttribute(QStringLiteral("id"), QStringLiteral("AStd::Asset")); 1331 account.setAttribute(QStringLiteral("name"), QStringLiteral("Asset")); 1332 account.setAttribute(QStringLiteral("number"), QString()); 1333 account.setAttribute(QStringLiteral("type"), QStringLiteral("9")); 1334 account.setAttribute(QStringLiteral("institution"), QString()); 1335 account.setAttribute(QStringLiteral("parentaccount"), QString()); 1336 account.setAttribute(QStringLiteral("lastmodified"), QString()); 1337 account.setAttribute(QStringLiteral("lastreconciled"), QString()); 1338 account.setAttribute(QStringLiteral("opened"), QString()); 1339 account.setAttribute(QStringLiteral("currency"), stdUnit); 1340 account.setAttribute(QStringLiteral("description"), QString()); 1341 1342 QDomElement subaccounts = doc.createElement(QStringLiteral("SUBACCOUNTS")); 1343 account.appendChild(subaccounts); 1344 accountAsset = subaccounts; 1345 } 1346 1347 { 1348 QDomElement account = doc.createElement(QStringLiteral("ACCOUNT")); 1349 accounts.appendChild(account); 1350 1351 account.setAttribute(QStringLiteral("id"), QStringLiteral("AStd::Liability")); 1352 account.setAttribute(QStringLiteral("name"), QStringLiteral("Liability")); 1353 account.setAttribute(QStringLiteral("number"), QString()); 1354 account.setAttribute(QStringLiteral("type"), QStringLiteral("10")); 1355 account.setAttribute(QStringLiteral("institution"), QString()); 1356 account.setAttribute(QStringLiteral("parentaccount"), QString()); 1357 account.setAttribute(QStringLiteral("lastmodified"), QString()); 1358 account.setAttribute(QStringLiteral("lastreconciled"), QString()); 1359 account.setAttribute(QStringLiteral("opened"), QString()); 1360 account.setAttribute(QStringLiteral("currency"), stdUnit); 1361 account.setAttribute(QStringLiteral("description"), QString()); 1362 1363 QDomElement subaccounts = doc.createElement(QStringLiteral("SUBACCOUNTS")); 1364 account.appendChild(subaccounts); 1365 } 1366 1367 { 1368 QDomElement account = doc.createElement(QStringLiteral("ACCOUNT")); 1369 accounts.appendChild(account); 1370 1371 account.setAttribute(QStringLiteral("id"), QStringLiteral("AStd::Income")); 1372 account.setAttribute(QStringLiteral("name"), QStringLiteral("Income")); 1373 account.setAttribute(QStringLiteral("number"), QString()); 1374 account.setAttribute(QStringLiteral("type"), QStringLiteral("12")); 1375 account.setAttribute(QStringLiteral("institution"), QString()); 1376 account.setAttribute(QStringLiteral("parentaccount"), QString()); 1377 account.setAttribute(QStringLiteral("lastmodified"), QString()); 1378 account.setAttribute(QStringLiteral("lastreconciled"), QString()); 1379 account.setAttribute(QStringLiteral("opened"), QString()); 1380 account.setAttribute(QStringLiteral("currency"), stdUnit); 1381 account.setAttribute(QStringLiteral("description"), QString()); 1382 1383 QDomElement subaccounts = doc.createElement(QStringLiteral("SUBACCOUNTS")); 1384 account.appendChild(subaccounts); 1385 accountIncome = subaccounts; 1386 } 1387 1388 { 1389 QDomElement account = doc.createElement(QStringLiteral("ACCOUNT")); 1390 accounts.appendChild(account); 1391 1392 account.setAttribute(QStringLiteral("id"), QStringLiteral("AStd::Expense")); 1393 account.setAttribute(QStringLiteral("name"), QStringLiteral("Expense")); 1394 account.setAttribute(QStringLiteral("number"), QString()); 1395 account.setAttribute(QStringLiteral("type"), QStringLiteral("13")); 1396 account.setAttribute(QStringLiteral("institution"), QString()); 1397 account.setAttribute(QStringLiteral("parentaccount"), QString()); 1398 account.setAttribute(QStringLiteral("lastmodified"), QString()); 1399 account.setAttribute(QStringLiteral("lastreconciled"), QString()); 1400 account.setAttribute(QStringLiteral("opened"), QString()); 1401 account.setAttribute(QStringLiteral("currency"), stdUnit); 1402 account.setAttribute(QStringLiteral("description"), QString()); 1403 1404 QDomElement subaccounts = doc.createElement(QStringLiteral("SUBACCOUNTS")); 1405 account.appendChild(subaccounts); 1406 accountExpense = subaccounts; 1407 } 1408 1409 SKGObjectBase::SKGListSKGObjectBase objects; 1410 IFOKDO(err, m_importer->getDocument()->getObjects(QStringLiteral("v_account"), QString(), objects)) 1411 int nb = objects.count(); 1412 IFOK(err) { 1413 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export accounts"), nb); 1414 for (int i = 0; !err && i < nb; ++i) { 1415 SKGAccountObject obj(objects.at(i)); 1416 QDomElement account = doc.createElement(QStringLiteral("ACCOUNT")); 1417 accounts.appendChild(account); 1418 1419 account.setAttribute(QStringLiteral("id"), getKmyUniqueIdentifier(obj)); 1420 account.setAttribute(QStringLiteral("name"), obj.getName()); 1421 account.setAttribute(QStringLiteral("number"), obj.getNumber()); 1422 account.setAttribute(QStringLiteral("type"), obj.getType() == SKGAccountObject::CREDITCARD ? QStringLiteral("4") : 1423 (obj.getType() == SKGAccountObject::INVESTMENT ? QStringLiteral("7") : 1424 (obj.getType() == SKGAccountObject::ASSETS ? QStringLiteral("9") : 1425 (obj.getType() == SKGAccountObject::WALLET ? QStringLiteral("3") : 1426 (obj.getType() == SKGAccountObject::LOAN ? QStringLiteral("10") : 1427 QStringLiteral("1")))))); 1428 1429 SKGBankObject bank; 1430 err = obj.getBank(bank); 1431 account.setAttribute(QStringLiteral("institution"), getKmyUniqueIdentifier(bank)); 1432 1433 account.setAttribute(QStringLiteral("parentaccount"), QStringLiteral("AStd::Asset")); 1434 account.setAttribute(QStringLiteral("lastmodified"), QString()); 1435 account.setAttribute(QStringLiteral("lastreconciled"), QString()); 1436 account.setAttribute(QStringLiteral("opened"), QString()); 1437 SKGUnitObject unit; 1438 obj.getUnit(unit); 1439 QString unitS = SKGUnitObject::getInternationalCode(unit.getName()); 1440 if (unitS.isEmpty()) { 1441 unitS = QStringLiteral("EUR"); 1442 } 1443 account.setAttribute(QStringLiteral("currency"), unitS); 1444 account.setAttribute(QStringLiteral("description"), QString()); 1445 1446 // Bookmarked account 1447 QDomElement keyvaluepairs = doc.createElement(QStringLiteral("KEYVALUEPAIRS")); 1448 account.appendChild(keyvaluepairs); 1449 if (obj.isBookmarked()) { 1450 QDomElement pair = doc.createElement(QStringLiteral("PAIR")); 1451 keyvaluepairs.appendChild(pair); 1452 pair.setAttribute(QStringLiteral("key"), QStringLiteral("PreferredAccount")); 1453 pair.setAttribute(QStringLiteral("value"), QStringLiteral("Yes")); 1454 } 1455 // Closed account 1456 if (obj.isClosed()) { 1457 QDomElement pair = doc.createElement(QStringLiteral("PAIR")); 1458 keyvaluepairs.appendChild(pair); 1459 pair.setAttribute(QStringLiteral("key"), QStringLiteral("mm-closed")); 1460 pair.setAttribute(QStringLiteral("value"), QStringLiteral("yes")); 1461 } 1462 1463 // Maximum and minimum limits 1464 if (obj.isMaxLimitAmountEnabled()) { 1465 QDomElement pair = doc.createElement(QStringLiteral("PAIR")); 1466 keyvaluepairs.appendChild(pair); 1467 pair.setAttribute(QStringLiteral("key"), QStringLiteral("maxCreditAbsolute")); 1468 pair.setAttribute(QStringLiteral("value"), kmyValue(-obj.getMaxLimitAmount())); 1469 } 1470 if (obj.isMinLimitAmountEnabled()) { 1471 QDomElement pair = doc.createElement(QStringLiteral("PAIR")); 1472 keyvaluepairs.appendChild(pair); 1473 pair.setAttribute(QStringLiteral("key"), QStringLiteral("minBalanceAbsolute")); 1474 pair.setAttribute(QStringLiteral("value"), kmyValue(obj.getMinLimitAmount())); 1475 } 1476 1477 // Add it in asset 1478 QDomElement subaccount = doc.createElement(QStringLiteral("SUBACCOUNT")); 1479 accountAsset.appendChild(subaccount); 1480 subaccount.setAttribute(QStringLiteral("id"), getKmyUniqueIdentifier(obj)); 1481 1482 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 1483 } 1484 1485 SKGENDTRANSACTION(m_importer->getDocument(), err) 1486 } 1487 1488 nbAccounts = nb; 1489 return err; 1490 } 1491 1492 SKGError SKGImportPluginKmy::exportFile() 1493 { 1494 // Initialisation 1495 m_opTreated.clear(); 1496 1497 if (m_importer->getDocument() == nullptr) { 1498 return SKGError(ERR_ABORT, i18nc("Error message", "Invalid parameters")); 1499 } 1500 SKGError err; 1501 SKGTRACEINFUNCRC(2, err) 1502 1503 // Open file 1504 KCompressionDevice file(m_importer->getLocalFileName(false), KCompressionDevice::GZip); 1505 if (!file.open(QIODevice::WriteOnly)) { 1506 err.setReturnCode(ERR_INVALIDARG).setMessage(i18nc("Error message", "Save file '%1' failed", m_importer->getFileName().toDisplayString())); 1507 } else { 1508 QDomDocument doc(QStringLiteral("KMYMONEY-FILE")); 1509 QDomComment comment = doc.createComment(QStringLiteral("Generated by libskgbankmodeler")); 1510 doc.appendChild(comment); 1511 1512 QDomElement root = doc.createElement(QStringLiteral("KMYMONEY-FILE")); 1513 doc.appendChild(root); 1514 { 1515 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Export step", "Export %1 file", "KMY"), 8); 1516 IFOK(err) { 1517 // Step 1-<FILEINFO> 1518 IFOKDO(err, exportHeader(doc, root)) 1519 IFOKDO(err, m_importer->getDocument()->stepForward(1)) 1520 1521 // // Step 2-<INSTITUTIONS> 1522 IFOKDO(err, exportInstitutions(doc, root)) 1523 IFOKDO(err, m_importer->getDocument()->stepForward(2)) 1524 1525 // Step 3-<PAYEES> 1526 IFOKDO(err, exportPayees(doc, root)) 1527 IFOKDO(err, m_importer->getDocument()->stepForward(3)) 1528 1529 // Step 4-<ACCOUNTS> 1530 // Std accounts 1531 QString stdUnit = SKGUnitObject::getInternationalCode(m_importer->getDocument()->getPrimaryUnit().Name); 1532 if (stdUnit.isEmpty()) { 1533 stdUnit = QStringLiteral("EUR"); 1534 } 1535 1536 QDomElement accountIncome; 1537 QDomElement accountExpense; 1538 QDomElement accounts; 1539 1540 int nbAccounts = 0; 1541 IFOKDO(err, exportAccounts(doc, root, stdUnit, accounts, accountIncome, accountExpense, nbAccounts)) 1542 IFOKDO(err, m_importer->getDocument()->stepForward(4)) 1543 1544 // Step 5 1545 IFOKDO(err, exportCategories(doc, accounts, stdUnit, accountIncome, accountExpense, nbAccounts)) 1546 IFOKDO(err, m_importer->getDocument()->stepForward(5)) 1547 1548 // Step 6-<TRANSACTIONS> 1549 IFOKDO(err, exportTransactions(doc, root, stdUnit)) 1550 1551 // Step 6-<SCHEDULES> 1552 IFOKDO(err, exportSchedules(doc, root)) 1553 IFOKDO(err, m_importer->getDocument()->stepForward(6)) 1554 1555 // Step 7-<BUDGETS> 1556 IFOKDO(err, exportBudgets(doc, root)) 1557 IFOKDO(err, m_importer->getDocument()->stepForward(7)) 1558 1559 // Step 8-<SECURITIES> and <CURRENCIES> 1560 IFOKDO(err, exportSecurities(doc, root, stdUnit)) 1561 1562 // Save file 1563 IFOK(err) { 1564 file.write(doc.toString().toUtf8()); 1565 } 1566 IFOKDO(err, m_importer->getDocument()->stepForward(8)) 1567 } 1568 1569 SKGENDTRANSACTION(m_importer->getDocument(), err) 1570 } 1571 1572 file.close(); 1573 } 1574 1575 // Clean 1576 m_opTreated.clear(); 1577 1578 return err; 1579 } 1580 1581 SKGError SKGImportPluginKmy::exportOperation(const SKGOperationObject& iOperation, QDomDocument& iDoc, QDomElement& iTransaction) 1582 { 1583 SKGError err; 1584 SKGTRACEINFUNCRC(2, err) 1585 if (!m_opTreated.contains(getKmyUniqueIdentifier(iOperation))) { 1586 QDomElement transaction = iDoc.createElement(QStringLiteral("TRANSACTION")); 1587 iTransaction.appendChild(transaction); 1588 1589 SKGUnitObject unit; 1590 iOperation.getUnit(unit); 1591 1592 QString date = iOperation.getAttribute(QStringLiteral("d_date")); 1593 transaction.setAttribute(QStringLiteral("id"), getKmyUniqueIdentifier(iOperation)); 1594 transaction.setAttribute(QStringLiteral("entrydate"), date); 1595 transaction.setAttribute(QStringLiteral("postdate"), date); 1596 transaction.setAttribute(QStringLiteral("memo"), iOperation.getComment()); 1597 transaction.setAttribute(QStringLiteral("commodity"), SKGUnitObject::getInternationalCode(unit.getName())); 1598 1599 QString reconcileflag = (iOperation.getStatus() == SKGOperationObject::MARKED ? QStringLiteral("1") : (iOperation.getStatus() == SKGOperationObject::CHECKED ? QStringLiteral("2") : QStringLiteral("0"))); 1600 1601 SKGAccountObject act; 1602 IFOKDO(err, iOperation.getParentAccount(act)) 1603 1604 QDomElement splits = iDoc.createElement(QStringLiteral("SPLITS")); 1605 transaction.appendChild(splits); 1606 1607 QDomElement split = iDoc.createElement(QStringLiteral("SPLIT")); 1608 splits.appendChild(split); 1609 1610 SKGPayeeObject payeeObject; 1611 iOperation.getPayee(payeeObject); 1612 QString payeeId = (payeeObject.getID() != 0 ? getKmyUniqueIdentifier(payeeObject) : QString()); 1613 1614 int indexSubOp = 1; 1615 1616 // Split for account 1617 split.setAttribute(QStringLiteral("payee"), payeeId); 1618 split.setAttribute(QStringLiteral("reconciledate"), QString()); 1619 split.setAttribute(QStringLiteral("id"), "S" % SKGServices::intToString(indexSubOp++).rightJustified(4, '0')); 1620 double val2 = SKGServices::stringToDouble(iOperation.getAttribute(QStringLiteral("f_QUANTITY"))); 1621 split.setAttribute(QStringLiteral("shares"), SKGImportPluginKmy::kmyValue(val2)); 1622 split.setAttribute(QStringLiteral("action"), QString()); 1623 split.setAttribute(QStringLiteral("bankid"), QString()); 1624 split.setAttribute(QStringLiteral("number"), iOperation.getNumber()); 1625 split.setAttribute(QStringLiteral("reconcileflag"), reconcileflag); 1626 split.setAttribute(QStringLiteral("memo"), iOperation.getComment()); 1627 QString originalAmount = iOperation.getProperty(QStringLiteral("SKG_OP_ORIGINAL_AMOUNT")); 1628 if (!originalAmount.isEmpty()) { 1629 val2 = qAbs(SKGServices::stringToDouble(originalAmount)) * (val2 / qAbs(val2)); 1630 } 1631 split.setAttribute(QStringLiteral("value"), SKGImportPluginKmy::kmyValue(val2)); 1632 split.setAttribute(QStringLiteral("account"), getKmyUniqueIdentifier(act)); 1633 1634 SKGOperationObject obj2; 1635 if (!err && iOperation.isTransfer(obj2)) { 1636 // It is a Transfer 1637 QString reconcileflag2 = (obj2.getStatus() == SKGOperationObject::MARKED ? QStringLiteral("1") : (obj2.getStatus() == SKGOperationObject::CHECKED ? QStringLiteral("2") : QStringLiteral("0"))); 1638 1639 SKGAccountObject act2; 1640 IFOKDO(err, obj2.getParentAccount(act2)) 1641 1642 QDomElement split2 = iDoc.createElement(QStringLiteral("SPLIT")); 1643 splits.appendChild(split2); 1644 1645 // Split for account 1646 val2 = -val2; 1647 split2.setAttribute(QStringLiteral("payee"), payeeId); 1648 split2.setAttribute(QStringLiteral("reconciledate"), QString()); 1649 split2.setAttribute(QStringLiteral("id"), "S" % SKGServices::intToString(indexSubOp++).rightJustified(4, '0')); 1650 split2.setAttribute(QStringLiteral("shares"), SKGImportPluginKmy::kmyValue(SKGServices::stringToDouble(obj2.getAttribute(QStringLiteral("f_QUANTITY"))))); 1651 split2.setAttribute(QStringLiteral("action"), QString()); 1652 split2.setAttribute(QStringLiteral("bankid"), QString()); 1653 split2.setAttribute(QStringLiteral("number"), obj2.getNumber()); 1654 split2.setAttribute(QStringLiteral("reconcileflag"), reconcileflag2); 1655 split2.setAttribute(QStringLiteral("memo"), obj2.getComment()); 1656 split2.setAttribute(QStringLiteral("value"), SKGImportPluginKmy::kmyValue(val2)); 1657 split2.setAttribute(QStringLiteral("account"), getKmyUniqueIdentifier(act2)); 1658 1659 m_opTreated.insert(getKmyUniqueIdentifier(obj2)); 1660 } else { 1661 SKGObjectBase::SKGListSKGObjectBase subops; 1662 IFOKDO(err, iOperation.getSubOperations(subops)) 1663 int nb2 = subops.count(); 1664 for (int j = 0; !err && j < nb2; ++j) { 1665 QDomElement split2 = iDoc.createElement(QStringLiteral("SPLIT")); 1666 splits.appendChild(split2); 1667 1668 SKGSubOperationObject subop(subops.at(j)); 1669 SKGCategoryObject cat; 1670 subop.getCategory(cat); 1671 split2.setAttribute(QStringLiteral("payee"), payeeId); 1672 split2.setAttribute(QStringLiteral("reconciledate"), QString()); 1673 split2.setAttribute(QStringLiteral("id"), "S" % SKGServices::intToString(indexSubOp++).rightJustified(4, '0')); 1674 QString shape3 = SKGImportPluginKmy::kmyValue(-subop.getQuantity()); 1675 split2.setAttribute(QStringLiteral("shares"), shape3); 1676 split2.setAttribute(QStringLiteral("action"), QString()); 1677 split2.setAttribute(QStringLiteral("bankid"), QString()); 1678 split2.setAttribute(QStringLiteral("number"), iOperation.getNumber()); 1679 split2.setAttribute(QStringLiteral("reconcileflag"), reconcileflag); 1680 split2.setAttribute(QStringLiteral("memo"), subop.getComment()); 1681 split2.setAttribute(QStringLiteral("value"), shape3); 1682 split2.setAttribute(QStringLiteral("account"), date == QStringLiteral("0000-00-00") ? QStringLiteral("AStd::Equity") : (cat.getID() != 0 ? getKmyUniqueIdentifier(cat) : QString())); 1683 } 1684 } 1685 1686 m_opTreated.insert(getKmyUniqueIdentifier(iOperation)); 1687 } 1688 return err; 1689 } 1690 1691 QString SKGImportPluginKmy::kmyValue(double iValue) 1692 { 1693 QString output; 1694 for (int i = 0; output.isEmpty() && i < 11; ++i) { 1695 QString d = SKGServices::doubleToString(pow(10, i) * iValue); 1696 if (d.indexOf('.') == -1) { 1697 output = d % '/' % SKGServices::intToString(qPow(10, i)); 1698 } 1699 } 1700 return output; 1701 } 1702 1703 double SKGImportPluginKmy::toKmyValue(const QString& iString) 1704 { 1705 double output = 0; 1706 QStringList vals = SKGServices::splitCSVLine(iString, '/'); 1707 if (vals.count() == 1) { 1708 output = SKGServices::stringToDouble(vals.at(0)); 1709 } else if (vals.count() == 2) { 1710 output = SKGServices::stringToDouble(vals.at(0)) / SKGServices::stringToDouble(vals.at(1)); 1711 } 1712 return output; 1713 } 1714 1715 QString SKGImportPluginKmy::getKmyUniqueIdentifier(const SKGObjectBase& iObject) 1716 { 1717 QString id; 1718 if (iObject.getID() != 0) { 1719 QString table = iObject.getRealTable(); 1720 if (table == QStringLiteral("operation") || table == QStringLiteral("suboperation")) { 1721 // T000000000000003623 1722 id = 'T' % SKGServices::intToString(iObject.getID()).rightJustified(18, '0'); 1723 } else if (table == QStringLiteral("payee")) { 1724 // P000030 1725 id = 'P' % SKGServices::intToString(iObject.getID()).rightJustified(6, '0'); 1726 } else { 1727 id = iObject.getUniqueID(); 1728 } 1729 } 1730 return id; 1731 } 1732 1733 QString SKGImportPluginKmy::getMimeTypeFilter() const 1734 { 1735 return "*.kmy|" % i18nc("A file format", "KMyMoney document"); 1736 } 1737 1738 #include <skgimportpluginkmy.moc>