File indexing completed on 2024-06-09 05:03:28

0001 /*
0002     SPDX-FileCopyrightText: 2007 Thomas Baumgart <ipwizard@users.sourceforge.net>
0003     SPDX-FileCopyrightText: 2017 Łukasz Wojniłowicz <lukasz.wojnilowicz@gmail.com>
0004     SPDX-License-Identifier: GPL-2.0-or-later
0005 */
0006 
0007 #include "kaccounttypepage.h"
0008 #include "kaccounttypepage_p.h"
0009 
0010 // ----------------------------------------------------------------------------
0011 // QT Includes
0012 
0013 #include <QDate>
0014 #include <QDialog>
0015 #include <QLabel>
0016 #include <QPointer>
0017 #include <QPushButton>
0018 
0019 // ----------------------------------------------------------------------------
0020 // KDE Includes
0021 
0022 #include <KLineEdit>
0023 #include <KLocalizedString>
0024 #include <KMessageBox>
0025 
0026 // ----------------------------------------------------------------------------
0027 // Project Includes
0028 
0029 #include "accountsmodel.h"
0030 #include "kbrokeragepage.h"
0031 #include "kcreditcardschedulepage.h"
0032 #include "kequitypriceupdatedlg.h"
0033 #include "kgeneralloaninfopage.h"
0034 #include "kguiutils.h"
0035 #include "khierarchypage.h"
0036 #include "kmymoneycurrencyselector.h"
0037 #include "kmymoneygeneralcombo.h"
0038 #include "kmymoneysettings.h"
0039 #include "kmymoneywizardpage.h"
0040 #include "knewaccountwizard.h"
0041 #include "knewaccountwizard_p.h"
0042 #include "mymoneyaccount.h"
0043 #include "mymoneyenums.h"
0044 #include "mymoneyfile.h"
0045 #include "mymoneymoney.h"
0046 #include "mymoneyprice.h"
0047 #include "mymoneysecurity.h"
0048 #include "wizardpage.h"
0049 
0050 using namespace eMyMoney;
0051 
0052 namespace NewAccountWizard
0053 {
0054 AccountTypePage::AccountTypePage(Wizard* wizard) :
0055     QWidget(wizard),
0056     WizardPage<Wizard>(*new AccountTypePagePrivate(wizard), StepAccount, this, wizard)
0057 {
0058     Q_D(AccountTypePage);
0059     d->ui->setupUi(this);
0060     d->m_showPriceWarning = true;
0061     d->ui->m_typeSelection->insertItem(i18n("Checking"), (int)Account::Type::Checkings, 0);
0062     d->ui->m_typeSelection->setItemIcon(0, Icons::get(Icon::Checking));
0063     d->ui->m_typeSelection->insertItem(i18n("Savings"), (int)Account::Type::Savings, 1);
0064     d->ui->m_typeSelection->setItemIcon(1, Icons::get(Icon::Savings));
0065     d->ui->m_typeSelection->insertItem(i18n("Credit Card"), (int)Account::Type::CreditCard, 2);
0066     d->ui->m_typeSelection->setItemIcon(2, Icons::get(Icon::CreditCard));
0067     d->ui->m_typeSelection->insertItem(i18n("Cash"), (int)Account::Type::Cash, 3);
0068     d->ui->m_typeSelection->setItemIcon(3, Icons::get(Icon::Cash));
0069     d->ui->m_typeSelection->insertItem(i18n("Loan"), (int)Account::Type::Loan, 4);
0070     d->ui->m_typeSelection->setItemIcon(4, Icons::get(Icon::Loan));
0071     d->ui->m_typeSelection->insertItem(i18n("Investment"), (int)Account::Type::Investment, 5);
0072     d->ui->m_typeSelection->setItemIcon(5, Icons::get(Icon::Investment));
0073     d->ui->m_typeSelection->insertItem(i18n("Asset"), (int)Account::Type::Asset, 6);
0074     d->ui->m_typeSelection->setItemIcon(6, Icons::get(Icon::Asset));
0075     d->ui->m_typeSelection->insertItem(i18n("Liability"), (int)Account::Type::Liability, 7);
0076     d->ui->m_typeSelection->setItemIcon(7, Icons::get(Icon::Liability));
0077     if (KMyMoneySettings::expertMode()) {
0078         d->ui->m_typeSelection->insertItem(i18n("Equity"), (int)Account::Type::Equity, 8);
0079         d->ui->m_typeSelection->setItemIcon(8, Icons::get(Icon::Equity));
0080     }
0081 
0082     d->ui->m_typeSelection->setCurrentItem((int)Account::Type::Checkings);
0083 
0084     d->ui->m_currencyComboBox->setSecurity(MyMoneyFile::instance()->baseCurrency());
0085 
0086     d->m_mandatoryGroup->add(d->ui->m_accountName);
0087     d->m_mandatoryGroup->add(d->ui->m_conversionRate);
0088 
0089     d->ui->m_conversionRate->setValue(MyMoneyMoney::ONE);
0090     slotUpdateCurrency();
0091 
0092     connect(d->ui->m_typeSelection, &KMyMoneyGeneralCombo::itemSelected, this, &AccountTypePage::slotUpdateType);
0093     connect(d->ui->m_currencyComboBox, static_cast<void (QComboBox::*)(int)>(&QComboBox::activated), this, &AccountTypePage::slotUpdateCurrency);
0094     /// @todo fix this logic with new amount edit logic (at least check)
0095     connect(d->ui->m_conversionRate, &AmountEdit::textChanged, this, &AccountTypePage::slotUpdateConversionRate);
0096     connect(d->ui->m_conversionRate, &AmountEdit::amountChanged, this, &AccountTypePage::slotPriceWarning);
0097     connect(d->ui->m_onlineQuote, &QAbstractButton::clicked, this, &AccountTypePage::slotGetOnlineQuote);
0098 }
0099 
0100 AccountTypePage::~AccountTypePage()
0101 {
0102 }
0103 
0104 void AccountTypePage::slotUpdateType(int i)
0105 {
0106     Q_D(AccountTypePage);
0107     hideShowPages(static_cast<Account::Type>(i));
0108     const bool enabled = accountTypeSupportsOpeningBalance(static_cast<Account::Type>(i));
0109     d->ui->m_openingBalance->setEnabled(enabled);
0110     d->ui->m_openingBalanceLabel->setEnabled(enabled);
0111 }
0112 
0113 void AccountTypePage::hideShowPages(Account::Type accountType) const
0114 {
0115     Q_D(const AccountTypePage);
0116     bool hideSchedulePage = (accountType != Account::Type::CreditCard)
0117                             && (accountType != Account::Type::Loan);
0118     bool hideLoanPage     = (accountType != Account::Type::Loan);
0119     d->m_wizard->d_func()->setStepHidden(StepDetails, hideLoanPage);
0120     d->m_wizard->d_func()->setStepHidden(StepPayments, hideLoanPage);
0121     d->m_wizard->d_func()->setStepHidden(StepFees, hideLoanPage);
0122     d->m_wizard->d_func()->setStepHidden(StepSchedule, hideSchedulePage);
0123     d->m_wizard->d_func()->setStepHidden(StepPayout, (accountType != Account::Type::Loan));
0124     d->m_wizard->d_func()->setStepHidden(StepBroker, accountType != Account::Type::Investment);
0125     d->m_wizard->d_func()->setStepHidden(StepParentAccount, accountType == Account::Type::Loan);
0126     // Force an update of the steps in case the list has changed
0127     d->m_wizard->reselectStep();
0128 }
0129 
0130 KMyMoneyWizardPage* AccountTypePage::nextPage() const
0131 {
0132     Q_D(const AccountTypePage);
0133     if (accountType() == Account::Type::Loan)
0134         return d->m_wizard->d_func()->m_generalLoanInfoPage;
0135     if (accountType() == Account::Type::CreditCard)
0136         return d->m_wizard->d_func()->m_schedulePage;
0137     if (accountType() == Account::Type::Investment)
0138         return d->m_wizard->d_func()->m_brokeragepage;
0139     return d->m_wizard->d_func()->m_hierarchyPage;
0140 }
0141 
0142 QWidget* AccountTypePage::initialFocusWidget() const
0143 {
0144     Q_D(const AccountTypePage);
0145     return d->ui->m_accountName;
0146 }
0147 
0148 void AccountTypePage::slotUpdateCurrency()
0149 {
0150     Q_D(AccountTypePage);
0151     MyMoneyAccount acc;
0152     acc.setAccountType(accountType());
0153 
0154     d->ui->m_openingBalance->setPrecision(MyMoneyMoney::denomToPrec(acc.fraction(currency())));
0155 
0156     bool show =  d->ui->m_currencyComboBox->security().id() != MyMoneyFile::instance()->baseCurrency().id();
0157     d->ui->m_conversionLabel->setVisible(show);
0158     d->ui->m_conversionRate->setVisible(show);
0159     d->ui->m_conversionExample->setVisible(show);
0160     d->ui->m_onlineQuote->setVisible(show);
0161     d->ui->m_conversionRate->setEnabled(show);       // make sure to include/exclude in mandatoryGroup
0162     d->ui->m_conversionRate->setPrecision(d->ui->m_currencyComboBox->security().pricePrecision());
0163     d->m_mandatoryGroup->changed();
0164     slotUpdateConversionRate(d->ui->m_conversionRate->text());
0165 }
0166 
0167 void AccountTypePage::slotGetOnlineQuote()
0168 {
0169     Q_D(AccountTypePage);
0170     QString id = MyMoneyFile::instance()->baseCurrency().id() + ' ' + d->ui->m_currencyComboBox->security().id();
0171     QPointer<KEquityPriceUpdateDlg> dlg = new KEquityPriceUpdateDlg(this, id);
0172     if (dlg->exec() == QDialog::Accepted) {
0173         const MyMoneyPrice &price = dlg->price(id);
0174         if (price.isValid()) {
0175             d->ui->m_conversionRate->setValue(price.rate(d->ui->m_currencyComboBox->security().id()));
0176             if (price.date() != d->ui->m_openingDate->date()) {
0177                 priceWarning(true);
0178             }
0179         }
0180     }
0181     delete dlg;
0182 }
0183 
0184 void AccountTypePage::slotPriceWarning()
0185 {
0186     priceWarning(false);
0187 }
0188 
0189 void AccountTypePage::priceWarning(bool always)
0190 {
0191     Q_D(AccountTypePage);
0192     if (d->m_showPriceWarning || always) {
0193         KMessageBox::information(this, i18n("Please make sure to enter the correct conversion for the selected opening date. If you requested an online quote it might be provided for a different date."), i18n("Check date"));
0194     }
0195     d->m_showPriceWarning = false;
0196 }
0197 
0198 void AccountTypePage::slotUpdateConversionRate(const QString& txt)
0199 {
0200     Q_D(AccountTypePage);
0201     d->ui->m_conversionExample->setText(i18n("1 %1 equals %2", MyMoneyFile::instance()->baseCurrency().tradingSymbol(), MyMoneyMoney(txt).formatMoney(d->ui->m_currencyComboBox->security().tradingSymbol(), d->ui->m_currencyComboBox->security().pricePrecision())));
0202 }
0203 
0204 bool AccountTypePage::isComplete() const
0205 {
0206     Q_D(const AccountTypePage);
0207     // check that the conversion rate is positive if enabled
0208     bool rc = !d->ui->m_conversionRate->isVisible() || (!d->ui->m_conversionRate->value().isZero() && !d->ui->m_conversionRate->value().isNegative());
0209     if (!rc) {
0210         d->m_wizard->d_func()->m_nextButton->setToolTip(i18n("Conversion rate is not positive"));
0211 
0212     } else {
0213         rc = KMyMoneyWizardPage::isComplete();
0214 
0215         if (!rc) {
0216             d->m_wizard->d_func()->m_nextButton->setToolTip(i18n("No account name supplied"));
0217         }
0218     }
0219     hideShowPages(accountType());
0220     return rc;
0221 }
0222 
0223 bool AccountTypePage::accountTypeSupportsOpeningBalance(Account::Type type) const
0224 {
0225     switch(type) {
0226     case Account::Type::Equity:
0227     case Account::Type::Investment:
0228         return false;
0229     default:
0230         break;
0231     }
0232     return true;
0233 }
0234 
0235 Account::Type AccountTypePage::accountType() const
0236 {
0237     Q_D(const AccountTypePage);
0238     return static_cast<Account::Type>(d->ui->m_typeSelection->currentItem());
0239 }
0240 
0241 const MyMoneySecurity& AccountTypePage::currency() const
0242 {
0243     Q_D(const AccountTypePage);
0244     return d->ui->m_currencyComboBox->security();
0245 }
0246 
0247 void AccountTypePage::setAccount(const MyMoneyAccount& acc)
0248 {
0249     Q_D(AccountTypePage);
0250     if (acc.accountType() != Account::Type::Unknown) {
0251         if (acc.accountType() == Account::Type::AssetLoan) {
0252             d->ui->m_typeSelection->setCurrentItem((int)Account::Type::Loan);
0253         } else {
0254             d->ui->m_typeSelection->setCurrentItem((int)acc.accountType());
0255         }
0256     }
0257     d->ui->m_openingDate->setDate(acc.openingDate());
0258     d->ui->m_accountName->setText(acc.name());
0259     d->m_parentAccountId = acc.parentAccountId();
0260 }
0261 
0262 MyMoneyAccount AccountTypePage::parentAccount()
0263 {
0264     Q_D(AccountTypePage);
0265     const auto file = MyMoneyFile::instance();
0266     const auto acc = file->accountsModel()->itemById(d->m_parentAccountId);
0267     // in case we don't have a parent account or its group does
0268     // not match the selected account type, we use the corresponding
0269     // standard top level account
0270     if (acc.id().isEmpty() || (acc.accountGroup() != acc.accountGroup(accountType()))) {
0271         switch (accountType()) {
0272         case Account::Type::CreditCard:
0273         case Account::Type::Liability:
0274         case Account::Type::Loan: // Can be either but we return liability here
0275             return file->liability();
0276             break;
0277         case Account::Type::Equity:
0278             return file->equity();
0279         default:
0280             break;
0281         }
0282         return file->asset();
0283     }
0284     return acc;
0285 }
0286 
0287 bool AccountTypePage::allowsParentAccount() const
0288 {
0289     return accountType() != Account::Type::Loan;
0290 }
0291 }