File indexing completed on 2024-05-26 05:10:42

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  * A skrooge plugin to payee transactions
0008  *
0009  * @author Stephane MANKOWSKI
0010  */
0011 #include "skgpayeeplugin.h"
0012 
0013 #include <kaboutdata.h>
0014 #include <kactioncollection.h>
0015 #include <kpluginfactory.h>
0016 #include <kstandardaction.h>
0017 
0018 #include "skgdocumentbank.h"
0019 #include "skgpayee_settings.h"
0020 #include "skgpayeepluginwidget.h"
0021 #include "skgtraces.h"
0022 #include "skgtransactionmng.h"
0023 
0024 /**
0025  * This plugin factory.
0026  */
0027 K_PLUGIN_CLASS_WITH_JSON(SKGPayeePlugin, "metadata.json")
0028 
0029 SKGPayeePlugin::SKGPayeePlugin(QWidget* iWidget, QObject* iParent, const QVariantList& /*iArg*/) : SKGInterfacePlugin(iParent), m_currentBankDocument(nullptr)
0030 {
0031     Q_UNUSED(iWidget)
0032     SKGTRACEINFUNC(10)
0033 }
0034 
0035 SKGPayeePlugin::~SKGPayeePlugin()
0036 {
0037     SKGTRACEINFUNC(10)
0038     m_currentBankDocument = nullptr;
0039 }
0040 
0041 bool SKGPayeePlugin::setupActions(SKGDocument* iDocument)
0042 {
0043     SKGTRACEINFUNC(10)
0044 
0045     if (qobject_cast<SKGDocumentBank*>(iDocument) == nullptr) {
0046         return false;
0047     }
0048 
0049     m_currentBankDocument = iDocument;
0050 
0051     setComponentName(QStringLiteral("skrooge_payee"), title());
0052     setXMLFile(QStringLiteral("skrooge_payee.rc"));
0053 
0054     // Actions
0055     QStringList overlaydelete;
0056     overlaydelete.push_back(QStringLiteral("edit-delete"));
0057 
0058     auto deleteUnusedPayeesAction = new QAction(SKGServices::fromTheme(icon(), overlaydelete), i18nc("Verb", "Delete unused payees"), this);
0059     connect(deleteUnusedPayeesAction, &QAction::triggered, this, &SKGPayeePlugin::deleteUnusedPayees);
0060     registerGlobalAction(QStringLiteral("clean_delete_unused_payees"), deleteUnusedPayeesAction);
0061 
0062     // ------------
0063     auto actTmp = new QAction(SKGServices::fromTheme(icon()), i18nc("Verb", "Open similar payees…"), this);
0064     actTmp->setData(QString("skg://skrooge_payee_plugin/?title_icon=" % icon() % "&title=" % SKGServices::encodeForUrl(i18nc("Noun, a list of items", "Similar payees")) %
0065                             "&whereClause=" % SKGServices::encodeForUrl(QStringLiteral("EXISTS (SELECT 1 FROM payee p2 WHERE p2.id<>v_payee_display.id AND upper(p2.t_name)=upper(v_payee_display.t_name) AND p2.t_name<>v_payee_display.t_name)"))));
0066     connect(actTmp, &QAction::triggered, SKGMainPanel::getMainPanel(), [ = ]() {
0067         SKGMainPanel::getMainPanel()->SKGMainPanel::openPage();
0068     });
0069     registerGlobalAction(QStringLiteral("view_open_similar_payees"), actTmp);
0070 
0071     return true;
0072 }
0073 
0074 SKGTabPage* SKGPayeePlugin::getWidget()
0075 {
0076     SKGTRACEINFUNC(10)
0077     return new SKGPayeePluginWidget(SKGMainPanel::getMainPanel(), m_currentBankDocument);
0078 }
0079 
0080 KConfigSkeleton* SKGPayeePlugin::getPreferenceSkeleton()
0081 {
0082     return skgpayee_settings::self();
0083 }
0084 
0085 QString SKGPayeePlugin::title() const
0086 {
0087     return i18nc("Noun, something that is used to track items", "Payees");
0088 }
0089 
0090 QString SKGPayeePlugin::icon() const
0091 {
0092     return QStringLiteral("user-group-properties");
0093 }
0094 
0095 QString SKGPayeePlugin::toolTip() const
0096 {
0097     return i18nc("A tool tip", "Payees management");
0098 }
0099 
0100 int SKGPayeePlugin::getOrder() const
0101 {
0102     return 28;
0103 }
0104 
0105 QStringList SKGPayeePlugin::tips() const
0106 {
0107     QStringList output;
0108     output.push_back(i18nc("Description of a tips", "<p>… <a href=\"skg://skrooge_payee_plugin\">payees</a> can be merged by drag & drop.</p>"));
0109     return output;
0110 }
0111 
0112 bool SKGPayeePlugin::isInPagesChooser() const
0113 {
0114     return true;
0115 }
0116 
0117 SKGAdviceList SKGPayeePlugin::advice(const QStringList& iIgnoredAdvice)
0118 {
0119     SKGTRACEINFUNC(10)
0120     SKGAdviceList output;
0121     // Check unused payee
0122     if (!iIgnoredAdvice.contains(QStringLiteral("skgpayeeplugin_unused"))) {
0123         bool exist = false;
0124         m_currentBankDocument->existObjects(QStringLiteral("payee LEFT JOIN operation ON operation.r_payee_id=payee.id"), QStringLiteral("operation.id IS NULL"), exist);
0125         if (exist) {
0126             SKGAdvice ad;
0127             ad.setUUID(QStringLiteral("skgpayeeplugin_unused"));
0128             ad.setPriority(5);
0129             ad.setShortMessage(i18nc("Advice on making the best (short)", "Many unused payees"));
0130             ad.setLongMessage(i18nc("Advice on making the best (long)", "You can improve performances by removing payees for which no transaction is registered."));
0131             SKGAdvice::SKGAdviceActionList autoCorrections;
0132             {
0133                 SKGAdvice::SKGAdviceAction a;
0134                 a.Title = QStringLiteral("skg://clean_delete_unused_payees");
0135                 a.IsRecommended = true;
0136                 autoCorrections.push_back(a);
0137             }
0138             ad.setAutoCorrections(autoCorrections);
0139             output.push_back(ad);
0140         }
0141     }
0142 
0143     // Check payee with different case
0144     if (!iIgnoredAdvice.contains(QStringLiteral("skgpayeeplugin_case"))) {
0145         bool exist = false;
0146         m_currentBankDocument->existObjects(QStringLiteral("payee"), QStringLiteral("EXISTS (SELECT 1 FROM payee p2 WHERE p2.id>payee.id AND p2.t_name=payee.t_name COLLATE NOCASE AND p2.t_name<>payee.t_name)"), exist);
0147         if (exist) {
0148             SKGAdvice ad;
0149             ad.setUUID(QStringLiteral("skgpayeeplugin_case"));
0150             ad.setPriority(3);
0151             ad.setShortMessage(i18nc("Advice on making the best (short)", "Some payees seem to be identical"));
0152             ad.setLongMessage(i18nc("Advice on making the best (long)", "Some payee seem to be identical but with different syntax. They could be merged."));
0153             QStringList autoCorrections;
0154             autoCorrections.push_back(QStringLiteral("skg://view_open_similar_payees"));
0155             ad.setAutoCorrections(autoCorrections);
0156             output.push_back(ad);
0157         }
0158     }
0159     return output;
0160 }
0161 
0162 void SKGPayeePlugin::deleteUnusedPayees() const
0163 {
0164     SKGError err;
0165     _SKGTRACEINFUNCRC(10, err)
0166     if (m_currentBankDocument != nullptr) {
0167         SKGBEGINTRANSACTION(*m_currentBankDocument, i18nc("Noun, name of the user action", "Delete unused payees"), err)
0168 
0169         // Modification of payee object
0170         QString sql = QStringLiteral("DELETE FROM payee  WHERE id IN (SELECT payee.id FROM payee LEFT JOIN operation ON operation.r_payee_id=payee.id WHERE operation.id IS NULL)");
0171         err = m_currentBankDocument->executeSqliteOrder(sql);
0172     }
0173 
0174     // status bar
0175     IFOKDO(err, SKGError(0, i18nc("Successful message after an user action", "Unused payees deleted")))
0176     else {
0177         err.addError(ERR_FAIL, i18nc("Error message", "Unused payees deletion failed"));
0178     }
0179 
0180     // Display error
0181     SKGMainPanel::displayErrorMessage(err);
0182 }
0183 
0184 #include <skgpayeeplugin.moc>