File indexing completed on 2024-05-26 05:09:43

0001 /*
0002     SPDX-FileCopyrightText: 2014-2015 Romain Bignon <romain@symlink.me>
0003     SPDX-FileCopyrightText: 2014-2015 Florent Fourcot <weboob@flo.fourcot.fr>
0004     SPDX-FileCopyrightText: 2016 Christian David <christian-david@web.de>
0005     SPDX-FileCopyrightText: 2017 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0006     SPDX-FileCopyrightText: 2019 Thomas Baumgart <tbaumgart@kde.org>
0007     SPDX-FileCopyrightText: 2021 Dawid Wróbel <me@dawidwrobel.com>
0008     SPDX-License-Identifier: GPL-2.0-or-later
0009 */
0010 
0011 #include "woob.h"
0012 #include <config-kmymoney.h>
0013 
0014 #include <memory>
0015 
0016 // ----------------------------------------------------------------------------
0017 // QT Includes
0018 
0019 #include <QFutureWatcher>
0020 #include <QProgressDialog>
0021 #include <QtConcurrentRun>
0022 
0023 // ----------------------------------------------------------------------------
0024 // KDE Includes
0025 
0026 #include <KLocalizedString>
0027 #include <KMessageBox>
0028 #include <KPluginFactory>
0029 
0030 // ----------------------------------------------------------------------------
0031 // Project Includes
0032 
0033 #include "accountsettings.h"
0034 #include "mapaccountwizard.h"
0035 #include "woobinterface.h"
0036 
0037 #include "mymoneyaccount.h"
0038 #include "mymoneykeyvaluecontainer.h"
0039 #include "mymoneystatement.h"
0040 #include "statementinterface.h"
0041 
0042 class WoobPrivate
0043 {
0044 public:
0045     WoobPrivate()
0046         : accountSettings(nullptr)
0047     {
0048     }
0049 
0050     ~WoobPrivate()
0051     {
0052     }
0053 
0054     bool checkInitialized() const
0055     {
0056         if (!woob.isPythonInitialized()) {
0057             KMessageBox::error(
0058                 nullptr,
0059                 i18n("Woob plugin failed to fully initialize, most likely due to a missing or a misconfigured Python environment. Please refer to the "
0060                      "manual on how to fix it."));
0061             return false;
0062         } else if (!woob.isWoobInitialized()) {
0063             KMessageBox::error(
0064                 nullptr,
0065                 i18n("Woob plugin failed to fully initialize, most likely due to a missing or a misconfigured Woob Python module. Please refer to the "
0066                      "manual on how to fix it."));
0067             return false;
0068         }
0069 
0070         return true;
0071     }
0072 
0073     WoobInterface woob;
0074     QFutureWatcher<WoobInterface::Account> watcher;
0075     std::unique_ptr<QProgressDialog> progress;
0076     AccountSettings* accountSettings;
0077 };
0078 
0079 Woob::Woob(QObject* parent, const KPluginMetaData& metaData, const QVariantList& args)
0080     : KMyMoneyPlugin::Plugin(parent, metaData, args)
0081     , d_ptr(new WoobPrivate)
0082 {
0083     Q_INIT_RESOURCE(woob);
0084 
0085     const auto rcFileName = QLatin1String("woob.rc");
0086     setXMLFile(rcFileName);
0087 
0088     qDebug("Plugins: woob loaded");
0089 }
0090 
0091 Woob::~Woob()
0092 {
0093     Q_D(Woob);
0094     delete d;
0095     qDebug("Plugins: woob unloaded");
0096 }
0097 
0098 void Woob::plug(KXMLGUIFactory* guiFactory)
0099 {
0100     Q_UNUSED(guiFactory)
0101     Q_D(Woob);
0102     connect(&d->watcher, &QFutureWatcher<WoobInterface::Account>::finished, this, &Woob::gotAccount);
0103 }
0104 
0105 void Woob::unplug()
0106 {
0107     Q_D(Woob);
0108     disconnect(&d->watcher, &QFutureWatcher<WoobInterface::Account>::finished, this, &Woob::gotAccount);
0109 }
0110 
0111 void Woob::protocols(QStringList& protocolList) const
0112 {
0113     protocolList << "woob";
0114 }
0115 
0116 QWidget* Woob::accountConfigTab(const MyMoneyAccount& account, QString& tabName)
0117 {
0118     Q_D(Woob);
0119     const MyMoneyKeyValueContainer& kvp = account.onlineBankingSettings();
0120     tabName = i18n("Woob configuration");
0121 
0122     d->accountSettings = new AccountSettings(account, 0);
0123     d->accountSettings->loadUi(kvp);
0124 
0125     return d->accountSettings;
0126 }
0127 
0128 MyMoneyKeyValueContainer Woob::onlineBankingSettings(const MyMoneyKeyValueContainer& current)
0129 {
0130     Q_D(Woob);
0131     MyMoneyKeyValueContainer kvp(current);
0132     kvp["provider"] = objectName().toLower();
0133     if (d->accountSettings) {
0134         d->accountSettings->loadKvp(kvp);
0135     }
0136     return kvp;
0137 }
0138 
0139 bool Woob::mapAccount(const MyMoneyAccount& acc, MyMoneyKeyValueContainer& onlineBankingSettings)
0140 {
0141     Q_D(Woob);
0142     Q_UNUSED(acc);
0143 
0144     bool rc = false;
0145 
0146     if (d->checkInitialized()) {
0147         QPointer<MapAccountWizard> w = new MapAccountWizard(nullptr, &d->woob);
0148         if (w->exec() == QDialog::Accepted && w != nullptr) {
0149             onlineBankingSettings.setValue("wb-backend", w->currentBackend());
0150             onlineBankingSettings.setValue("wb-id", w->currentAccount());
0151             onlineBankingSettings.setValue("wb-max", "0");
0152             rc = true;
0153         }
0154         delete w;
0155     }
0156 
0157     return rc;
0158 }
0159 
0160 bool Woob::updateAccount(const MyMoneyAccount& kacc, bool moreAccounts)
0161 {
0162     Q_D(Woob);
0163     Q_UNUSED(moreAccounts);
0164 
0165     if (d->checkInitialized()) {
0166         QString bname = kacc.onlineBankingSettings().value("wb-backend");
0167         QString id = kacc.onlineBankingSettings().value("wb-id");
0168         QString max = kacc.onlineBankingSettings().value("wb-max");
0169 
0170         d->progress = std::make_unique<QProgressDialog>(nullptr);
0171         d->progress->setWindowTitle(i18n("Connecting to bank..."));
0172         d->progress->setLabelText(i18n("Retrieving transactions..."));
0173         d->progress->setModal(true);
0174         d->progress->setCancelButton(nullptr);
0175         d->progress->setMinimum(0);
0176         d->progress->setMaximum(0);
0177         d->progress->setMinimumDuration(0);
0178 
0179         QFuture<WoobInterface::Account> future = QtConcurrent::run(&d->woob, &WoobInterface::getAccount, bname, id, max);
0180         d->watcher.setFuture(future);
0181 
0182         d->progress->exec();
0183         d->progress.reset();
0184 
0185         return true;
0186     } else
0187         return false;
0188 }
0189 
0190 void Woob::gotAccount()
0191 {
0192     Q_D(Woob);
0193     WoobInterface::Account acc = d->watcher.result();
0194 
0195     MyMoneyAccount kacc = statementInterface()->account("wb-id", acc.id);
0196     MyMoneyStatement ks;
0197 
0198     ks.m_accountId = kacc.id();
0199     ks.m_strAccountName = acc.name;
0200     ks.m_closingBalance = acc.balance;
0201     if (acc.transactions.length() > 0)
0202         ks.m_dateEnd = acc.transactions.front().date;
0203 
0204 #if 0
0205     switch (acc.type) {
0206     case Woob::Account::TYPE_CHECKING:
0207         ks.m_eType = MyMoneyStatement::etCheckings;
0208         break;
0209     case Woob::Account::TYPE_SAVINGS:
0210         ks.m_eType = MyMoneyStatement::etSavings;
0211         break;
0212     case Woob::Account::TYPE_MARKET:
0213         ks.m_eType = MyMoneyStatement::etInvestment;
0214         break;
0215     case Woob::Account::TYPE_DEPOSIT:
0216     case Woob::Account::TYPE_LOAN:
0217     case Woob::Account::TYPE_JOINT:
0218     case Woob::Account::TYPE_UNKNOWN:
0219         break;
0220     }
0221 #endif
0222 
0223     for (QListIterator<WoobInterface::Transaction> it(acc.transactions); it.hasNext();) {
0224         WoobInterface::Transaction tr = it.next();
0225         MyMoneyStatement::Transaction kt;
0226 
0227         kt.m_strBankID = QLatin1String("ID ") + tr.id;
0228         kt.m_datePosted = tr.rdate;
0229         kt.m_amount = tr.amount;
0230         kt.m_strMemo = tr.raw;
0231         kt.m_strPayee = tr.label;
0232 
0233         ks.m_listTransactions += kt;
0234     }
0235 
0236     statementInterface()->import(ks);
0237 
0238     d->progress->hide();
0239 }
0240 
0241 K_PLUGIN_CLASS_WITH_JSON(Woob, "woob.json")
0242 
0243 #include "woob.moc"