File indexing completed on 2024-06-16 04:47:18
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 AFB120 import / export. 0008 * 0009 * @author Stephane MANKOWSKI / Guillaume DE BURE 0010 */ 0011 #include "skgimportpluginafb120.h" 0012 0013 #include <kpluginfactory.h> 0014 0015 #include <qcryptographichash.h> 0016 #include <qfile.h> 0017 #include <qmath.h> 0018 0019 #include "skgbankincludes.h" 0020 #include "skgimportexportmanager.h" 0021 #include "skgservices.h" 0022 #include "skgtraces.h" 0023 0024 /** 0025 * This plugin factory. 0026 */ 0027 K_PLUGIN_CLASS_WITH_JSON(SKGImportPluginAFB120, "metadata.json") 0028 0029 SKGImportPluginAFB120::SKGImportPluginAFB120(QObject* iImporter, const QVariantList& iArg) 0030 : SKGImportPlugin(iImporter) 0031 { 0032 SKGTRACEINFUNC(10) 0033 Q_UNUSED(iArg) 0034 } 0035 0036 SKGImportPluginAFB120::~SKGImportPluginAFB120() 0037 = default; 0038 0039 bool SKGImportPluginAFB120::isImportPossible() 0040 { 0041 SKGTRACEINFUNC(10) 0042 return (m_importer->getDocument() == nullptr ? true : m_importer->getFileNameExtension() == QStringLiteral("AFB120") || m_importer->getFileNameExtension() == QStringLiteral("CFO")); 0043 } 0044 0045 double SKGImportPluginAFB120::toAmount(const QString& iAmount, int iNbDecimal) 0046 { 0047 QString amount = iAmount; 0048 QChar lastChar = amount.right(1).at(0); 0049 int codeAscii = lastChar.toLatin1(); 0050 int sign = (codeAscii > 79 && codeAscii != 123 ? -1 : 1); 0051 if (codeAscii == 123 || codeAscii == 125) { 0052 amount[amount.count() - 1] = '0'; 0053 } else { 0054 bool ok = false; 0055 amount[amount.count() - 1] = QChar(codeAscii + QChar('1').toLatin1() - QString(sign == -1 ? QStringLiteral("0x4A") : QStringLiteral("0x41")).toUInt(&ok, 16)); 0056 } 0057 return static_cast<double>(sign) * SKGServices::stringToDouble(amount) / qPow(10, iNbDecimal); 0058 } 0059 0060 SKGError SKGImportPluginAFB120::importFile() 0061 { 0062 if (m_importer->getDocument() == nullptr) { 0063 return SKGError(ERR_ABORT, i18nc("Error message", "Invalid parameters")); 0064 } 0065 SKGError err; 0066 SKGTRACEINFUNCRC(2, err) 0067 0068 // Begin transaction 0069 err = m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import %1 file", "AFB120"), 2); 0070 IFOK(err) { 0071 // Open file 0072 IFOK(err) { 0073 QFile file(m_importer->getLocalFileName()); 0074 if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) { 0075 err.setReturnCode(ERR_INVALIDARG).setMessage(i18nc("Error message", "Open file '%1' failed", m_importer->getFileName().toDisplayString())); 0076 } else { 0077 // Read lines 0078 QStringList lines; 0079 { 0080 QTextStream stream(&file); 0081 if (!m_importer->getCodec().isEmpty()) { 0082 stream.setCodec(m_importer->getCodec().toLatin1().constData()); 0083 } 0084 while (!stream.atEnd()) { 0085 // Read line 0086 QString line = stream.readLine().trimmed(); 0087 if (!line.isEmpty()) { 0088 lines.push_back(line); 0089 } 0090 } 0091 } 0092 // close file 0093 file.close(); 0094 0095 // Step 1 done 0096 IFOKDO(err, m_importer->getDocument()->stepForward(1)) 0097 0098 // Read lines 0099 SKGAccountObject account; 0100 SKGUnitObject unit; 0101 QString bankName = QStringLiteral("AFB120"); 0102 QString inititalAmount; 0103 0104 int nb = lines.count(); 0105 IFOKDO(err, m_importer->getDocument()->beginTransaction("#INTERNAL#" % i18nc("Import step", "Import transactions"), nb)) 0106 for (int i = 0; i < nb && !err; ++i) { 0107 // Read line 0108 const QString& line = lines.at(i); 0109 if (!line.isEmpty()) { 0110 if (line.startsWith(QLatin1String("01"))) { 0111 // Previous balance 0112 QString accountNumber = line.mid(22 - 1, 11); 0113 inititalAmount = line.mid(91 - 1, 14); 0114 0115 SKGObjectBase::SKGListSKGObjectBase listAccount; 0116 err = m_importer->getDocument()->getObjects(QStringLiteral("v_account"), "t_number='" % accountNumber % '\'', listAccount); 0117 IFOK(err) { 0118 if (listAccount.count() == 1) { 0119 // Yes ! Only one account found 0120 account = listAccount.at(0); 0121 err = m_importer->getDocument()->sendMessage(i18nc("An information message", "Using account '%1' for import", account.getName())); 0122 } else { 0123 if (listAccount.count() > 1) { 0124 err = m_importer->getDocument()->sendMessage(i18nc("An information message", "More than one possible account found.")); 0125 } 0126 0127 SKGBankObject bank(m_importer->getDocument()); 0128 IFOKDO(err, bank.setName(bankName)) 0129 IFOKDO(err, bank.setNumber(bankName)) 0130 if (!err && bank.load().isFailed()) { 0131 err = bank.save(); 0132 } 0133 IFOKDO(err, bank.addAccount(account)) 0134 IFOKDO(err, account.setName(accountNumber)) 0135 IFOKDO(err, account.setNumber(accountNumber)) 0136 IFOKDO(err, account.setType(SKGAccountObject::CURRENT)) 0137 if (!err && account.load().isFailed()) { 0138 err = account.save(); 0139 } 0140 IFOKDO(err, m_importer->getDocument()->sendMessage(i18nc("An information message", "Default account '%1' created for import", accountNumber))) 0141 } 0142 } 0143 } else if (line.startsWith(QLatin1String("04"))) { 0144 // Transaction 0145 QString unitCode = line.mid(17 - 1, 3); 0146 QString nbDecimal = line.mid(20 - 1, 1); 0147 // QString codeMode = line.mid(33 - 1, 2); 0148 QString dateJJMMAA = line.mid(35 - 1, 6); 0149 QString comment = line.mid(49 - 1, 31).trimmed(); 0150 QString amount = line.mid(91 - 1, 14); 0151 0152 // Initialize balance 0153 if (unit.getID() == 0) { 0154 err = SKGUnitObject::createCurrencyUnit(m_importer->getDocument(), unitCode, unit); 0155 if (account.getNbOperation() > 1) { 0156 IFOKDO(err, m_importer->getDocument()->sendMessage(i18nc("An information message", "The initial balance of '%1' has not been set because some transactions are already existing", account.getName()), SKGDocument::Warning)) 0157 } else { 0158 // Set initial balance 0159 IFOKDO(err, account.setInitialBalance(toAmount(inititalAmount, SKGServices::stringToInt(nbDecimal)), unit)) 0160 IFOKDO(err, account.save()) 0161 IFOKDO(err, m_importer->getDocument()->sendMessage(i18nc("An information message", "The initial balance of '%1' has been set with AFB120 file content", account.getName()))) 0162 } 0163 } 0164 0165 SKGOperationObject operation; 0166 IFOKDO(err, account.addOperation(operation, true)) 0167 IFOKDO(err, operation.setDate(SKGServices::stringToTime(SKGServices::dateToSqlString(dateJJMMAA, QStringLiteral("DDMMYYYY"))).date())) 0168 IFOKDO(err, operation.setUnit(unit)) 0169 IFOKDO(err, operation.setAttribute(QStringLiteral("t_imported"), QStringLiteral("T"))) 0170 IFOKDO(err, operation.setComment(comment)) 0171 QByteArray hash = QCryptographicHash::hash(line.toUtf8(), QCryptographicHash::Md5); 0172 IFOKDO(err, operation.setImportID(QStringLiteral("AFB120-") % hash.toHex())) 0173 IFOKDO(err, operation.save(false)) 0174 0175 SKGSubOperationObject subop; 0176 IFOKDO(err, operation.addSubOperation(subop)) 0177 IFOKDO(err, subop.setComment(comment)) 0178 IFOKDO(err, subop.setQuantity(toAmount(amount, SKGServices::stringToInt(nbDecimal)))) 0179 IFOKDO(err, subop.save(false, false)) 0180 } 0181 } 0182 IFOKDO(err, m_importer->getDocument()->stepForward(i + 1)) 0183 } 0184 SKGENDTRANSACTION(m_importer->getDocument(), err) 0185 0186 // Step 2 done 0187 IFOKDO(err, m_importer->getDocument()->stepForward(2)) 0188 } 0189 } 0190 } 0191 SKGENDTRANSACTION(m_importer->getDocument(), err) 0192 0193 return err; 0194 } 0195 0196 QString SKGImportPluginAFB120::getMimeTypeFilter() const 0197 { 0198 return "*.afb120 *.cfo|" % i18nc("A file format", "AFB120 file (cfomb)"); 0199 } 0200 0201 #include <skgimportpluginafb120.moc>