You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
kmymoney/kmymoney2/kmymoneyutils.cpp

485 lines
16 KiB

/***************************************************************************
kmymoneyutils.cpp - description
-------------------
begin : Wed Feb 5 2003
copyright : (C) 2000-2003 by Michael Edwardes
email : mte@users.sourceforge.net
Javier Campos Morales <javi_c@users.sourceforge.net>
Felix Rodriguez <frodriguez@users.sourceforge.net>
John C <thetacoturtle@users.sourceforge.net>
Thomas Baumgart <ipwizard@users.sourceforge.net>
Kevin Tambascio <ktambascio@users.sourceforge.net>
***************************************************************************/
/***************************************************************************
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
***************************************************************************/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
// ----------------------------------------------------------------------------
// TQt Includes
// ----------------------------------------------------------------------------
// TDE Headers
#include <tdelocale.h>
#include <tdeglobal.h>
#include <kiconloader.h>
#include <tdemessagebox.h>
#include <tdeconfig.h>
#include <kstandarddirs.h>
// ----------------------------------------------------------------------------
// Project Includes
#include <kmymoney/mymoneyfile.h>
#include <kmymoney/mymoneyforecast.h>
#include <kmymoney/kmymoneyglobalsettings.h>
#include <kmymoney/investtransactioneditor.h>
#include "kmymoneyutils.h"
KMyMoneyUtils::KMyMoneyUtils()
{
}
KMyMoneyUtils::~KMyMoneyUtils()
{
}
const TQString KMyMoneyUtils::accountTypeToString(const MyMoneyAccount::accountTypeE accountType)
{
return MyMoneyAccount::accountTypeToString(accountType);
}
MyMoneyAccount::accountTypeE KMyMoneyUtils::stringToAccountType(const TQString& type)
{
MyMoneyAccount::accountTypeE rc = MyMoneyAccount::UnknownAccountType;
TQString tmp = type.lower();
if(tmp == i18n("Checking").lower())
rc = MyMoneyAccount::Checkings;
else if(tmp == i18n("Savings").lower())
rc = MyMoneyAccount::Savings;
else if(tmp == i18n("Credit Card").lower())
rc = MyMoneyAccount::CreditCard;
else if(tmp == i18n("Cash").lower())
rc = MyMoneyAccount::Cash;
else if(tmp == i18n("Loan").lower())
rc = MyMoneyAccount::Loan;
else if(tmp == i18n("Certificate of Deposit").lower())
rc = MyMoneyAccount::CertificateDep;
else if(tmp == i18n("Investment").lower())
rc = MyMoneyAccount::Investment;
else if(tmp == i18n("Money Market").lower())
rc = MyMoneyAccount::MoneyMarket;
else if(tmp == i18n("Asset").lower())
rc = MyMoneyAccount::Asset;
else if(tmp == i18n("Liability").lower())
rc = MyMoneyAccount::Liability;
else if(tmp == i18n("Currency").lower())
rc = MyMoneyAccount::Currency;
else if(tmp == i18n("Income").lower())
rc = MyMoneyAccount::Income;
else if(tmp == i18n("Expense").lower())
rc = MyMoneyAccount::Expense;
else if(tmp == i18n("Investment Loan").lower())
rc = MyMoneyAccount::AssetLoan;
else if(tmp == i18n("Stock").lower())
rc = MyMoneyAccount::Stock;
else if(tmp == i18n("Equity").lower())
rc = MyMoneyAccount::Equity;
return rc;
}
MyMoneySecurity::eSECURITYTYPE KMyMoneyUtils::stringToSecurity(const TQString& txt)
{
MyMoneySecurity::eSECURITYTYPE rc = MyMoneySecurity::SECURITY_NONE;
TQString tmp = txt.lower();
if(tmp == i18n("Stock").lower())
rc = MyMoneySecurity::SECURITY_STOCK;
else if(tmp == i18n("Mutual Fund").lower())
rc = MyMoneySecurity::SECURITY_MUTUALFUND;
else if(tmp == i18n("Bond").lower())
rc = MyMoneySecurity::SECURITY_BOND;
else if(tmp == i18n("Currency").lower())
rc = MyMoneySecurity::SECURITY_CURRENCY;
return rc;
}
const TQString KMyMoneyUtils::securityTypeToString(const MyMoneySecurity::eSECURITYTYPE securityType)
{
return i18n(MyMoneySecurity::securityTypeToString(securityType).utf8());
}
const TQString KMyMoneyUtils::occurenceToString(const MyMoneySchedule::occurenceE occurence)
{
return i18n(MyMoneySchedule::occurenceToString(occurence).utf8());
}
const TQString KMyMoneyUtils::paymentMethodToString(MyMoneySchedule::paymentTypeE paymentType)
{
return i18n(MyMoneySchedule::paymentMethodToString(paymentType).utf8());
}
const TQString KMyMoneyUtils::weekendOptionToString(MyMoneySchedule::weekendOptionE weekendOption)
{
return i18n(MyMoneySchedule::weekendOptionToString(weekendOption).utf8());
}
const TQString KMyMoneyUtils::scheduleTypeToString(MyMoneySchedule::typeE type)
{
return i18n(MyMoneySchedule::scheduleTypeToString(type).utf8());
}
KGuiItem KMyMoneyUtils::scheduleNewGuiItem(void)
{
TDEIconLoader *ic = TDEGlobal::iconLoader();
KGuiItem splitGuiItem( i18n("&New Schedule..."),
TQIconSet(ic->loadIcon("document-new", TDEIcon::Small, TDEIcon::SizeSmall)),
i18n("Create a new schedule."),
i18n("Use this to create a new schedule."));
return splitGuiItem;
}
KGuiItem KMyMoneyUtils::accountsFilterGuiItem(void)
{
TDEIconLoader *ic = TDEGlobal::iconLoader();
KGuiItem splitGuiItem( i18n("&Filter"),
TQIconSet(ic->loadIcon("filter", TDEIcon::Small, TDEIcon::SizeSmall)),
i18n("Filter out accounts"),
i18n("Use this to filter out accounts"));
return splitGuiItem;
}
TQPixmap KMyMoneyUtils::billScheduleIcon(int size)
{
TDEIconLoader *ic = TDEGlobal::iconLoader();
return ic->loadIcon("billschedule", TDEIcon::User, size);
}
TQPixmap KMyMoneyUtils::depositScheduleIcon(int size)
{
TDEIconLoader *ic = TDEGlobal::iconLoader();
return ic->loadIcon("depositschedule", TDEIcon::User, size);
}
TQPixmap KMyMoneyUtils::transferScheduleIcon(int size)
{
TDEIconLoader *ic = TDEGlobal::iconLoader();
return ic->loadIcon("transferschedule", TDEIcon::User, size);
}
TQPixmap KMyMoneyUtils::scheduleIcon(int size)
{
TDEIconLoader *ic = TDEGlobal::iconLoader();
return ic->loadIcon("schedule", TDEIcon::User, size);
}
const char* homePageItems[] = {
I18N_NOOP("Payments"),
I18N_NOOP("Preferred accounts"),
I18N_NOOP("Payment accounts"),
I18N_NOOP("Favorite reports"),
I18N_NOOP("Forecast (schedule)"),
I18N_NOOP("Networth forecast"),
I18N_NOOP("Forecast (history)"),
I18N_NOOP("Assets and Liabilities"),
I18N_NOOP("Budget"),
I18N_NOOP("CashFlow"),
// insert new items above this comment
0
};
const TQString KMyMoneyUtils::homePageItemToString(const int idx)
{
TQString rc;
if(abs(idx) > 0 && abs(idx) < static_cast<int>(sizeof(homePageItems)/sizeof(homePageItems[0]))) {
rc = i18n(homePageItems[abs(idx-1)]);
}
return rc;
}
int KMyMoneyUtils::stringToHomePageItem(const TQString& txt)
{
int idx = 0;
for(idx = 0; homePageItems[idx] != 0; ++idx) {
if(txt == i18n(homePageItems[idx]))
return idx+1;
}
return 0;
}
bool KMyMoneyUtils::appendCorrectFileExt(TQString& str, const TQString& strExtToUse)
{
bool rc = false;
if(!str.isEmpty()) {
//find last . delminator
int nLoc = str.findRev('.');
if(nLoc != -1) {
TQString strExt, strTemp;
strTemp = str.left(nLoc + 1);
strExt = str.right(str.length() - (nLoc + 1));
if(strExt.find(strExtToUse, 0, FALSE) == -1) {
// if the extension given contains a period, we remove our's
if(strExtToUse.find('.') != -1)
strTemp = strTemp.left(strTemp.length()-1);
//append extension to make complete file name
strTemp.append(strExtToUse);
str = strTemp;
rc = true;
}
} else {
str.append(".");
str.append(strExtToUse);
rc = true;
}
}
return rc;
}
void KMyMoneyUtils::checkConstants(void)
{
Q_ASSERT(static_cast<int>(TDELocale::ParensAround) == static_cast<int>(MyMoneyMoney::ParensAround));
Q_ASSERT(static_cast<int>(TDELocale::BeforeQuantityMoney) == static_cast<int>(MyMoneyMoney::BeforeQuantityMoney));
Q_ASSERT(static_cast<int>(TDELocale::AfterQuantityMoney) == static_cast<int>(MyMoneyMoney::AfterQuantityMoney));
Q_ASSERT(static_cast<int>(TDELocale::BeforeMoney) == static_cast<int>(MyMoneyMoney::BeforeMoney));
Q_ASSERT(static_cast<int>(TDELocale::AfterMoney) == static_cast<int>(MyMoneyMoney::AfterMoney));
}
TQString KMyMoneyUtils::variableCSS(void)
{
TQColor tcolor = TDEGlobalSettings::textColor();
TQString css;
css += "<style type=\"text/css\">\n<!--\n";
css += TQString(".row-even, .item0 { background-color: %1; color: %2 }\n")
.arg((KMyMoneyGlobalSettings::listBGColor()).name()).arg(tcolor.name());
css += TQString(".row-odd, .item1 { background-color: %1; color: %2 }\n")
.arg((KMyMoneyGlobalSettings::listColor()).name()).arg(tcolor.name());
css += "-->\n</style>\n";
return css;
}
TQString KMyMoneyUtils::findResource(const char* type, const TQString& filename)
{
TQString language = TDEGlobal::locale()->language();
TQString country = TDEGlobal::locale()->country();
TQString rc, mask;
// check that the placeholder is present
if(!filename.find("%1")) {
tqWarning(TQString("%%1 not found in '%1'").arg(filename));
return filename;
}
// search the given resource
mask = filename.arg("_%1.%2");
rc = TDEGlobal::dirs()->findResource(type, mask.arg(country).arg(language));
if(rc.isEmpty()) {
mask = filename.arg("_%1");
rc = TDEGlobal::dirs()->findResource(type, mask.arg(language));
}
if(rc.isEmpty()) {
// tqDebug(TQString("html/home_%1.html not found").arg(country));
rc = TDEGlobal::dirs()->findResource(type, mask.arg(country));
}
if(rc.isEmpty()) {
rc = TDEGlobal::dirs()->findResource(type, filename.arg(""));
}
if(rc.isEmpty()) {
tqWarning(TQString("No resource found for (%1,%2)").arg(type).arg(filename));
}
return rc;
}
const MyMoneySplit KMyMoneyUtils::stockSplit(const MyMoneyTransaction& t)
{
TQValueList<MyMoneySplit>::ConstIterator it_s;
MyMoneySplit investmentAccountSplit;
for(it_s = t.splits().begin(); it_s != t.splits().end(); ++it_s) {
if(!(*it_s).accountId().isEmpty()) {
MyMoneyAccount acc = MyMoneyFile::instance()->account((*it_s).accountId());
if(acc.isInvest()) {
return *it_s;
}
// if we have a reference to an investment account, we remember it here
if(acc.accountType() == MyMoneyAccount::Investment)
investmentAccountSplit = *it_s;
}
}
// if we haven't found a stock split, we see if we've seen
// an investment account on the way. If so, we return it.
if(!investmentAccountSplit.id().isEmpty())
return investmentAccountSplit;
// if none was found, we return an empty split.
return MyMoneySplit();
}
KMyMoneyUtils::transactionTypeE KMyMoneyUtils::transactionType(const MyMoneyTransaction& t)
{
if(!stockSplit(t).id().isEmpty())
return InvestmentTransaction;
if(t.splitCount() < 2) {
return Unknown;
} else if(t.splitCount() > 2) {
// FIXME check for loan transaction here
return SplitTransaction;
}
TQString ida, idb;
ida = t.splits()[0].accountId();
idb = t.splits()[1].accountId();
if(ida.isEmpty() || idb.isEmpty())
return Unknown;
MyMoneyAccount a, b;
a = MyMoneyFile::instance()->account(ida);
b = MyMoneyFile::instance()->account(idb);
if((a.accountGroup() == MyMoneyAccount::Asset
|| a.accountGroup() == MyMoneyAccount::Liability)
&& (b.accountGroup() == MyMoneyAccount::Asset
|| b.accountGroup() == MyMoneyAccount::Liability))
return Transfer;
return Normal;
}
void KMyMoneyUtils::calculateAutoLoan(const MyMoneySchedule& schedule, MyMoneyTransaction& transaction, const TQMap<TQString, MyMoneyMoney>& balances)
{
try {
MyMoneyForecast::calculateAutoLoan(schedule, transaction, balances);
} catch (MyMoneyException* e) {
KMessageBox::detailedError(0, i18n("Unable to load schedule details"), e->what());
delete e;
}
}
TQString KMyMoneyUtils::nextCheckNumber(const MyMoneyAccount& acc)
{
// determine next check number
TQString number;
TQRegExp exp(TQString("(.*\\D)?(\\d+)(\\D.*)?"));
if(exp.search(acc.value("lastNumberUsed")) != -1) {
number = TQString("%1%2%3").arg(exp.cap(1)).arg(exp.cap(2).toULongLong() + 1).arg(exp.cap(3));
} else {
number = "1";
}
return number;
}
TQString KMyMoneyUtils::reconcileStateToString(MyMoneySplit::reconcileFlagE flag, bool text)
{
TQString txt;
if(text) {
switch(flag) {
case MyMoneySplit::NotReconciled:
txt = i18n("Reconcile state 'Not reconciled'", "Not reconciled");
break;
case MyMoneySplit::Cleared:
txt = i18n("Reconcile state 'Cleared'", "Cleared");
break;
case MyMoneySplit::Reconciled:
txt = i18n("Reconcile state 'Reconciled'", "Reconciled");
break;
case MyMoneySplit::Frozen:
txt = i18n("Reconcile state 'Frozen'", "Frozen");
break;
default:
txt = i18n("Unknown");
break;
}
} else {
switch(flag) {
case MyMoneySplit::NotReconciled:
break;
case MyMoneySplit::Cleared:
txt = i18n("Reconcile flag C", "C");
break;
case MyMoneySplit::Reconciled:
txt = i18n("Reconcile flag R", "R");
break;
case MyMoneySplit::Frozen:
txt = i18n("Reconcile flag F", "F");
break;
default:
txt = i18n("Flag for unknown reconciliation state", "?");
break;
}
}
return txt;
}
MyMoneyTransaction KMyMoneyUtils::scheduledTransaction(const MyMoneySchedule& schedule)
{
MyMoneyTransaction t = schedule.transaction();
try {
if (schedule.type() == MyMoneySchedule::TYPE_LOANPAYMENT) {
calculateAutoLoan(schedule, t, TQMap<TQString, MyMoneyMoney>());
}
} catch (MyMoneyException* e) {
tqDebug(TQString("Unable to load schedule details for '%1' during transaction match: %1").arg(schedule.name()).arg(e->what()));
delete e;
}
t.clearId();
t.setEntryDate(TQDate());
return t;
}
void KMyMoneyUtils::previouslyUsedCategories(const TQString& investmentAccount, TQString& feesId, TQString& interestId)
{
feesId = interestId = TQString();
MyMoneyFile* file = MyMoneyFile::instance();
try {
MyMoneyAccount acc = file->account(investmentAccount);
MyMoneyTransactionFilter filter(investmentAccount);
filter.setReportAllSplits(false);
// since we assume an investment account here, we need to collect the stock accounts as well
filter.addAccount(acc.accountList());
TQValueList< TQPair<MyMoneyTransaction, MyMoneySplit> > list;
file->transactionList(list, filter);
TQValueList< TQPair<MyMoneyTransaction, MyMoneySplit> >::const_iterator it_t;
for(it_t = list.begin(); it_t != list.end(); ++it_t) {
const MyMoneyTransaction& t = (*it_t).first;
const MyMoneySplit&s = (*it_t).second;
MyMoneySplit assetAccountSplit;
TQValueList<MyMoneySplit> feeSplits;
TQValueList<MyMoneySplit> interestSplits;
MyMoneySecurity security;
MyMoneySecurity currency;
MyMoneySplit::investTransactionTypeE transactionType;
InvestTransactionEditor::dissectTransaction(t, s, assetAccountSplit, feeSplits, interestSplits, security, currency, transactionType);
if(feeSplits.count() == 1) {
feesId = feeSplits.first().accountId();
}
if(interestSplits.count() == 1) {
interestId = interestSplits.first().accountId();
}
}
} catch(MyMoneyException *e) {
delete e;
}
}