File indexing completed on 2025-02-02 04:57:03
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 XML import / export. 0008 * 0009 * @author Stephane MANKOWSKI / Guillaume DE BURE 0010 */ 0011 #include "skgimportpluginxml.h" 0012 0013 #include <klocalizedstring.h> 0014 #include <kpluginfactory.h> 0015 0016 #include <qsavefile.h> 0017 #include <qfile.h> 0018 #include <QtXmlPatterns/qxmlquery.h> 0019 #include <qstandardpaths.h> 0020 0021 #include "skgbankincludes.h" 0022 #include "skgservices.h" 0023 #include "skgtraces.h" 0024 0025 /** 0026 * This plugin factory. 0027 */ 0028 K_PLUGIN_CLASS_WITH_JSON(SKGImportPluginXml, "metadata.json") 0029 0030 SKGImportPluginXml::SKGImportPluginXml(QObject* iImporter, const QVariantList& iArg) 0031 : SKGImportPlugin(iImporter) 0032 { 0033 SKGTRACEINFUNC(10) 0034 Q_UNUSED(iArg) 0035 } 0036 0037 SKGImportPluginXml::~SKGImportPluginXml() 0038 = default; 0039 0040 bool SKGImportPluginXml::isImportPossible() 0041 { 0042 SKGTRACEINFUNC(10) 0043 if (m_importer->getDocument() == nullptr) { 0044 return true; 0045 } 0046 if (m_importer->getFileNameExtension() != QStringLiteral("XML")) { 0047 return false; 0048 } 0049 return true; 0050 } 0051 0052 0053 SKGError SKGImportPluginXml::importFile() 0054 { 0055 if (m_importer->getDocument() == nullptr) { 0056 return SKGError(ERR_ABORT, i18nc("Error message", "Invalid parameters")); 0057 } 0058 SKGError err; 0059 SKGTRACEINFUNCRC(2, err) 0060 0061 // Determine the XML format 0062 QString format; 0063 QDomElement docElem; 0064 IFOKDO(err, m_importer->getXMLDocument(docElem)) 0065 IFOK(err) { 0066 if (docElem.tagName() == "skrooge") { 0067 // SKROOGE XML FORMAT 0068 format = "XML"; 0069 } else if (docElem.tagName() == "Document") { 0070 // ISO20022 XML FORMAT 0071 QFile file(m_importer->getLocalFileName()); 0072 if (!file.open(QIODevice::ReadOnly)) { 0073 err.setReturnCode(ERR_INVALIDARG).setMessage(i18nc("Error message", "Open file '%1' failed", m_importer->getFileName().toDisplayString())); 0074 } else { 0075 QTextStream xmlStream(file.readAll(), QIODevice::ReadOnly); 0076 QString xml = xmlStream.readAll().replace(QRegularExpression("<Document[^>]*>"), "<Document>"); 0077 QString out; 0078 QXmlQuery query(QXmlQuery::XSLT20); 0079 query.setFocus(xml); 0080 query.setQuery(QUrl::fromLocalFile(QStandardPaths::locate(QStandardPaths::GenericDataLocation, QStringLiteral("skrooge/ISO20022.xslt")))); 0081 query.evaluateTo(&out); 0082 SKGTRACEL(1) << "OUT=" << out << Qt::endl; 0083 0084 // Set the file without uncompression 0085 QString errorMsg; 0086 int errorLine = 0; 0087 int errorCol = 0; 0088 QDomDocument doc; 0089 bool contentOK = doc.setContent(out, &errorMsg, &errorLine, &errorCol); 0090 0091 if (!contentOK) { 0092 err.setReturnCode(ERR_ABORT).setMessage(i18nc("Error message", "%1-%2: '%3'", errorLine, errorCol, errorMsg)).addError(ERR_INVALIDARG, i18nc("Error message", "Invalid XML content in %1", out)); 0093 } else { 0094 // Get root 0095 format = "ISO20022"; 0096 docElem = doc.documentElement(); 0097 } 0098 } 0099 } else { 0100 err.setReturnCode(ERR_INVALIDARG).setMessage(i18nc("Error message", "Unknown XML format. Only Skrooge and ISO20022 XML formats are supported")); 0101 } 0102 } 0103 0104 // Build list of items to import 0105 QList<QString> types; 0106 types.append(QStringLiteral("unit")); 0107 types.append(QStringLiteral("unitvalue")); 0108 types.append(QStringLiteral("bank")); 0109 types.append(QStringLiteral("account")); 0110 types.append(QStringLiteral("payee")); 0111 types.append(QStringLiteral("refund")); 0112 types.append(QStringLiteral("rule")); 0113 types.append(QStringLiteral("category")); 0114 types.append(QStringLiteral("budget")); 0115 types.append(QStringLiteral("budgetrule")); 0116 types.append(QStringLiteral("operation")); 0117 types.append(QStringLiteral("suboperation")); 0118 types.append(QStringLiteral("recurrentoperation")); 0119 types.append(QStringLiteral("interest")); 0120 0121 auto nb = types.length(); 0122 IFOKDO(err, m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import %1 file", format), nb)) 0123 for (int i = 0; !err && i < nb; ++i) { 0124 auto type = types.at(i); 0125 QDomElement itemsList = docElem.firstChildElement(QStringLiteral("list_") + type); 0126 IFOKDO(err, m_importer->importItems(itemsList)); 0127 0128 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)); 0129 } 0130 0131 SKGENDTRANSACTION(m_importer->getDocument(), err) 0132 0133 IFOKDO(err, m_importer->getDocument()->executeSqliteOrder(QStringLiteral("ANALYZE"))) 0134 0135 return err; 0136 } 0137 0138 bool SKGImportPluginXml::isExportPossible() 0139 { 0140 SKGTRACEINFUNC(10) 0141 return (m_importer->getDocument() == nullptr ? true : m_importer->getFileNameExtension() == QStringLiteral("XML")); 0142 } 0143 0144 SKGError SKGImportPluginXml::exportFile() 0145 { 0146 SKGError err; 0147 QDomDocument doc; 0148 QVector<QString> ignore; 0149 ignore.append(QStringLiteral("parameters")); 0150 ignore.append(QStringLiteral("doctransaction")); 0151 ignore.append(QStringLiteral("doctransactionitem")); 0152 ignore.append(QStringLiteral("doctransactionmsg")); 0153 ignore.append(QStringLiteral("operationbalance")); 0154 ignore.append(QStringLiteral("budgetsuboperation")); 0155 ignore.append(QStringLiteral("node")); 0156 ignore.append(QStringLiteral("interest_result")); 0157 ignore.append(QStringLiteral("category.t_fullname")); 0158 ignore.append(QStringLiteral("operation.i_tmp")); 0159 ignore.append(QStringLiteral("suboperation.i_tmp")); 0160 ignore.append(QStringLiteral("unit.f_CURRENTAMOUNT_CACHE")); 0161 err = SKGServices::copySqliteDatabaseToXml(*(m_importer->getDocument()->getMainDatabase()), doc, &ignore); 0162 IFOK(err) { 0163 QSaveFile file(m_importer->getLocalFileName(false)); 0164 if (!file.open(QIODevice::WriteOnly)) { 0165 err.setReturnCode(ERR_INVALIDARG).setMessage(i18nc("Error message", "Save file '%1' failed", m_importer->getFileName().toDisplayString())); 0166 } else { 0167 QTextStream stream(&file); 0168 if (!m_importer->getCodec().isEmpty()) { 0169 stream.setCodec(m_importer->getCodec().toLatin1().constData()); 0170 } 0171 stream << doc.toString() << SKGENDL; 0172 0173 // Close file 0174 file.commit(); 0175 } 0176 } 0177 return err; 0178 } 0179 0180 QString SKGImportPluginXml::getMimeTypeFilter() const 0181 { 0182 return "*.xml|" % i18nc("A file format", "XML file"); 0183 } 0184 0185 #include <skgimportpluginxml.moc>