/*************************************************************************** mymoneyaccount.cpp ------------------- copyright : (C) 2000 by Michael Edwardes (C) 2002 by Thomas Baumagrt email : mte@users.sourceforge.net ipwizard@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. * * * ***************************************************************************/ // ---------------------------------------------------------------------------- // QT Includes #include #include #include // ---------------------------------------------------------------------------- // KDE Includes #include // ---------------------------------------------------------------------------- // Project Includes #include #include #include MyMoneyAccount::MyMoneyAccount() : m_fraction(-1) { m_accountType = UnknownAccountType; } MyMoneyAccount::~MyMoneyAccount() { } MyMoneyAccount::MyMoneyAccount(const TQString& id, const MyMoneyAccount& right) : MyMoneyObject(id) { *this = right; setId(id); } MyMoneyAccount::MyMoneyAccount(const TQDomElement& node) : MyMoneyObject(node), MyMoneyKeyValueContainer(node.elementsByTagName("KEYVALUEPAIRS").item(0).toElement()), m_fraction(-1) { if("ACCOUNT" != node.tagName()) throw new MYMONEYEXCEPTION("Node was not ACCOUNT"); setName(node.attribute("name")); // qDebug("Reading information for account %s", acc.name().data()); setParentAccountId(TQStringEmpty(node.attribute("tqparentaccount"))); setLastModified(stringToDate(TQStringEmpty(node.attribute("lastmodified")))); setLastReconciliationDate(stringToDate(TQStringEmpty(node.attribute("lastreconciled")))); if(!m_lastReconciliationDate.isValid()) { // for some reason, I was unable to access our own kvp at this point through // the value() method. It always returned empty strings. The workaround for // this is to construct a local kvp the same way as we have done before and // extract the value from it. // // Since we want to get rid of the lastStatementDate record anyway, this seems // to be ok for now. (ipwizard - 2008-08-14) TQString txt = MyMoneyKeyValueContainer(node.elementsByTagName("KEYVALUEPAIRS").item(0).toElement()).value("lastStatementDate"); if(!txt.isEmpty()) { setLastReconciliationDate(TQDate::fromString(txt, Qt::ISODate)); } } setInstitutionId(TQStringEmpty(node.attribute("institution"))); setNumber(TQStringEmpty(node.attribute("number"))); setOpeningDate(stringToDate(TQStringEmpty(node.attribute("opened")))); setCurrencyId(TQStringEmpty(node.attribute("currency"))); TQString tmp = TQStringEmpty(node.attribute("type")); bool bOK = false; int type = tmp.toInt(&bOK); if(bOK) { setAccountType(static_cast(type)); } else { qWarning("XMLREADER: Account %s had invalid or no account type information.", name().data()); } if(node.hasAttribute("openingbalance")) { if(!MyMoneyMoney(node.attribute("openingbalance")).isZero()) { TQString msg = i18n("Account %1 contains an opening balance. Please use a KMyMoney version >= 0.8 and < 0.9 to correct the problem.").tqarg(m_name); throw new MYMONEYEXCEPTION(msg); } } setDescription(node.attribute("description")); m_id = TQStringEmpty(node.attribute("id")); // qDebug("Account %s has id of %s, type of %d, tqparent is %s.", acc.name().data(), id.data(), type, acc.tqparentAccountId().data()); // Process any Sub-Account information found inside the account entry. m_accountList.clear(); TQDomNodeList nodeList = node.elementsByTagName("SUBACCOUNTS"); if(nodeList.count() > 0) { nodeList = nodeList.item(0).toElement().elementsByTagName("SUBACCOUNT"); for(unsigned int i = 0; i < nodeList.count(); ++i) { addAccountId(TQString(nodeList.item(i).toElement().attribute("id"))); } } nodeList = node.elementsByTagName("ONLINEBANKING"); if(nodeList.count() > 0) { TQDomNamedNodeMap attributes = nodeList.item(0).toElement().attributes(); for(unsigned int i = 0; i < attributes.count(); ++i) { const TQDomAttr& it_attr = attributes.item(i).toAttr(); m_onlineBankingSettings.setValue(it_attr.name().utf8(), it_attr.value()); } } } void MyMoneyAccount::setName(const TQString& name) { m_name = name; } void MyMoneyAccount::setNumber(const TQString& number) { m_number = number; } void MyMoneyAccount::setDescription(const TQString& desc) { m_description = desc; } void MyMoneyAccount::setInstitutionId(const TQString& id) { m_institution = id; } void MyMoneyAccount::setLastModified(const TQDate& date) { m_lastModified = date; } void MyMoneyAccount::setOpeningDate(const TQDate& date) { m_openingDate = date; } void MyMoneyAccount::setLastReconciliationDate(const TQDate& date) { // FIXME: for a limited time (maybe until we delivered 1.0) we // keep the last reconciliation date also in the KVP for backward // compatability. After that, the setValue() statemetn should be removed // and the XML ctor should remove the value completely from the KVP setValue("lastStatementDate", date.toString(Qt::ISODate)); m_lastReconciliationDate = date; } void MyMoneyAccount::setParentAccountId(const TQString& tqparent) { m_parentAccount = tqparent; } void MyMoneyAccount::setAccountType(const accountTypeE type) { m_accountType = type; } void MyMoneyAccount::addAccountId(const TQString& account) { if(!m_accountList.tqcontains(account)) m_accountList += account; } void MyMoneyAccount::removeAccountIds(void) { m_accountList.clear(); } void MyMoneyAccount::removeAccountId(const TQString& account) { TQStringList::Iterator it; it = m_accountList.tqfind(account); if(it != m_accountList.end()) m_accountList.remove(it); } MyMoneyAccount::accountTypeE MyMoneyAccount::accountGroup(MyMoneyAccount::accountTypeE type) { switch(type) { case MyMoneyAccount::Checkings: case MyMoneyAccount::Savings: case MyMoneyAccount::Cash: case MyMoneyAccount::Currency: case MyMoneyAccount::Investment: case MyMoneyAccount::MoneyMarket: case MyMoneyAccount::CertificateDep: case MyMoneyAccount::AssetLoan: case MyMoneyAccount::Stock: return MyMoneyAccount::Asset; case MyMoneyAccount::CreditCard: case MyMoneyAccount::Loan: return MyMoneyAccount::Liability; default: return type; } } bool MyMoneyAccount::operator == (const MyMoneyAccount& right) const { return (MyMoneyKeyValueContainer::operator==(right) && MyMoneyObject::operator==(right) && (m_accountList == right.m_accountList) && (m_accountType == right.m_accountType) && (m_lastModified == right.m_lastModified) && (m_lastReconciliationDate == right.m_lastReconciliationDate) && ((m_name.length() == 0 && right.m_name.length() == 0) || (m_name == right.m_name)) && ((m_number.length() == 0 && right.m_number.length() == 0) || (m_number == right.m_number)) && ((m_description.length() == 0 && right.m_description.length() == 0) || (m_description == right.m_description)) && (m_openingDate == right.m_openingDate) && (m_parentAccount == right.m_parentAccount) && (m_currencyId == right.m_currencyId) && (m_institution == right.m_institution) ); } MyMoneyAccount::accountTypeE MyMoneyAccount::accountGroup(void) const { return accountGroup(m_accountType); } void MyMoneyAccount::setCurrencyId(const TQString& id) { m_currencyId = id; } bool MyMoneyAccount::isAssetLiability(void) const { return accountGroup() == Asset || accountGroup() == Liability; } bool MyMoneyAccount::isIncomeExpense(void) const { return accountGroup() == Income || accountGroup() == Expense; } bool MyMoneyAccount::isLoan(void) const { return accountType() == Loan || accountType() == AssetLoan; } bool MyMoneyAccount::isInvest(void) const { return accountType() == Stock; } MyMoneyAccountLoan::MyMoneyAccountLoan(const MyMoneyAccount& acc) : MyMoneyAccount(acc) { } const MyMoneyMoney MyMoneyAccountLoan::loanAmount(void) const { return MyMoneyMoney(value("loan-amount")); } void MyMoneyAccountLoan::setLoanAmount(const MyMoneyMoney& amount) { setValue("loan-amount", amount.toString()); } const MyMoneyMoney MyMoneyAccountLoan::interestRate(const TQDate& date) const { MyMoneyMoney rate; TQString key; TQString val; if(!date.isValid()) return rate; key.sprintf("ir-%04d-%02d-%02d", date.year(), date.month(), date.day()); TQRegExp regExp("ir-(\\d{4})-(\\d{2})-(\\d{2})"); TQMap::ConstIterator it; for(it = pairs().begin(); it != pairs().end(); ++it) { if(regExp.search(it.key()) > -1) { if(qstrcmp(it.key(),key) <= 0) val = *it; else break; } else if(!val.isEmpty()) break; } if(!val.isEmpty()) { rate = MyMoneyMoney(val); } return rate; } void MyMoneyAccountLoan::setInterestRate(const TQDate& date, const MyMoneyMoney& value) { if(!date.isValid()) return; TQString key; key.sprintf("ir-%04d-%02d-%02d", date.year(), date.month(), date.day()); setValue(key, value.toString()); } MyMoneyAccountLoan::interestDueE MyMoneyAccountLoan::interestCalculation(void) const { TQString payTime(value("interest-calculation")); if(payTime == "paymentDue") return paymentDue; return paymentReceived; } void MyMoneyAccountLoan::setInterestCalculation(const MyMoneyAccountLoan::interestDueE onReception) { if(onReception == paymentDue) setValue("interest-calculation", "paymentDue"); else setValue("interest-calculation", "paymentReceived"); } const TQDate MyMoneyAccountLoan::nextInterestChange(void) const { TQDate rc; TQRegExp regExp("(\\d{4})-(\\d{2})-(\\d{2})"); if(regExp.search(value("interest-nextchange")) != -1) { rc.setYMD(regExp.cap(1).toInt(), regExp.cap(2).toInt(), regExp.cap(3).toInt()); } return rc; } void MyMoneyAccountLoan::setNextInterestChange(const TQDate& date) { setValue("interest-nextchange", date.toString(Qt::ISODate)); } int MyMoneyAccountLoan::interestChangeFrequency(int* unit) const { int rc = -1; if(unit) *unit = 1; TQRegExp regExp("(\\d+)/(\\d{1})"); if(regExp.search(value("interest-changefrequency")) != -1) { rc = regExp.cap(1).toInt(); if(unit != 0) { *unit = regExp.cap(2).toInt(); } } return rc; } void MyMoneyAccountLoan::setInterestChangeFrequency(const int amount, const int unit) { TQString val; val.sprintf("%d/%d", amount, unit); setValue("interest-changeFrequency", val); } const TQString MyMoneyAccountLoan::schedule(void) const { return TQString(value("schedule").latin1()); } void MyMoneyAccountLoan::setSchedule(const TQString& sched) { setValue("schedule", sched); } bool MyMoneyAccountLoan::fixedInterestRate(void) const { // make sure, that an empty kvp element returns true return !(value("fixed-interest") == "no"); } void MyMoneyAccountLoan::setFixedInterestRate(const bool fixed) { setValue("fixed-interest", fixed ? "yes" : "no"); if(fixed) { deletePair("interest-nextchange"); deletePair("interest-changeFrequency"); } } const MyMoneyMoney MyMoneyAccountLoan::finalPayment(void) const { return MyMoneyMoney(value("final-payment")); } void MyMoneyAccountLoan::setFinalPayment(const MyMoneyMoney& finalPayment) { setValue("final-payment", finalPayment.toString()); } unsigned int MyMoneyAccountLoan::term(void) const { return value("term").toUInt(); } void MyMoneyAccountLoan::setTerm(const unsigned int payments) { setValue("term", TQString::number(payments)); } const MyMoneyMoney MyMoneyAccountLoan::periodicPayment(void) const { return MyMoneyMoney(value("periodic-payment")); } void MyMoneyAccountLoan::setPeriodicPayment(const MyMoneyMoney& payment) { setValue("periodic-payment", payment.toString()); } const TQString MyMoneyAccountLoan::payee(void) const { return value("payee"); } void MyMoneyAccountLoan::setPayee(const TQString& payee) { setValue("payee", payee); } const TQString MyMoneyAccountLoan::interestAccountId(void) const { return TQString(); } void MyMoneyAccountLoan::setInterestAccountId(const TQString& /* id */) { } bool MyMoneyAccountLoan::hasReferenceTo(const TQString& id) const { return MyMoneyAccount::hasReferenceTo(id) || (id == payee()) || (id == schedule()); } void MyMoneyAccountLoan::setInterestCompounding(int frequency) { setValue("compoundingFrequency", TQString("%1").tqarg(frequency)); } int MyMoneyAccountLoan::interestCompounding(void) const { return value("compoundingFrequency").toInt(); } void MyMoneyAccount::writeXML(TQDomDocument& document, TQDomElement& tqparent) const { TQDomElement el = document.createElement("ACCOUNT"); writeBaseXML(document, el); el.setAttribute("tqparentaccount", tqparentAccountId()); el.setAttribute("lastreconciled", dateToString(lastReconciliationDate())); el.setAttribute("lastmodified", dateToString(lastModified())); el.setAttribute("institution", institutionId()); el.setAttribute("opened", dateToString(openingDate())); el.setAttribute("number", number()); // el.setAttribute("openingbalance", openingBalance().toString()); el.setAttribute("type", accountType()); el.setAttribute("name", name()); el.setAttribute("description", description()); if(!currencyId().isEmpty()) el.setAttribute("currency", currencyId()); //Add in subaccount information, if this account has subaccounts. if(accountCount()) { TQDomElement subAccounts = document.createElement("SUBACCOUNTS"); TQStringList::ConstIterator it; for(it = accountList().begin(); it != accountList().end(); ++it) { TQDomElement temp = document.createElement("SUBACCOUNT"); temp.setAttribute("id", (*it)); subAccounts.appendChild(temp); } el.appendChild(subAccounts); } // Write online banking settings if(m_onlineBankingSettings.pairs().count()) { TQDomElement onlinesettings = document.createElement("ONLINEBANKING"); TQMap::const_iterator it_key = m_onlineBankingSettings.pairs().begin(); while ( it_key != m_onlineBankingSettings.pairs().end() ) { onlinesettings.setAttribute(it_key.key(), it_key.data()); ++it_key; } el.appendChild(onlinesettings); } // FIXME drop the lastStatementDate record from the KVP when it is // not stored there after setLastReconciliationDate() has been changed // See comment there when this will happen // deletePair("lastStatementDate"); //Add in Key-Value Pairs for accounts. MyMoneyKeyValueContainer::writeXML(document, el); tqparent.appendChild(el); } bool MyMoneyAccount::hasReferenceTo(const TQString& id) const { return (id == m_institution) || (id == m_parentAccount) || (id == m_currencyId); } void MyMoneyAccount::setOnlineBankingSettings(const MyMoneyKeyValueContainer& values) { m_onlineBankingSettings = values; } const MyMoneyKeyValueContainer& MyMoneyAccount::onlineBankingSettings(void) const { return m_onlineBankingSettings; } void MyMoneyAccount::setClosed(bool closed) { if(closed) setValue("mm-closed", "yes"); else deletePair("mm-closed"); } bool MyMoneyAccount::isClosed(void) const { return !(value("mm-closed").isEmpty()); } int MyMoneyAccount::fraction(const MyMoneySecurity& sec) const { int fraction; if(m_accountType == Cash) fraction = sec.smallestCashFraction(); else fraction = sec.smallestAccountFraction(); return fraction; } int MyMoneyAccount::fraction(const MyMoneySecurity& sec) { if(m_accountType == Cash) m_fraction = sec.smallestCashFraction(); else m_fraction = sec.smallestAccountFraction(); return m_fraction; } int MyMoneyAccount::fraction(void) const { Q_ASSERT(m_fraction != -1); return m_fraction; } bool MyMoneyAccount::isCategory(void) const { return m_accountType == Income || m_accountType == Expense; } TQString MyMoneyAccount::brokerageName(void) const { if(m_accountType == Investment) return TQString("%1 (%2)").tqarg(m_name, i18n("Brokerage (suffix for account names)", "Brokerage")); return m_name; } void MyMoneyAccount::adjustBalance(const MyMoneySplit& s, bool reverse) { if(s.action() == MyMoneySplit::ActionSplitShares) { if(reverse) m_balance = m_balance / s.shares(); else m_balance = m_balance * s.shares(); } else { if(reverse) m_balance -= s.shares(); else m_balance += s.shares(); } } TQPixmap MyMoneyAccount::accountPixmap(bool reconcileFlag, int size) const { TQString icon; switch(accountType()) { default: if(accountGroup() == MyMoneyAccount::Asset) icon = "account-types_asset"; else icon = "account-types_liability"; break; case MyMoneyAccount::Investment: case MyMoneyAccount::Stock: case MyMoneyAccount::MoneyMarket: case MyMoneyAccount::CertificateDep: icon = "account-types_investments"; break; case MyMoneyAccount::Checkings: icon = "account-types_checking"; break; case MyMoneyAccount::Savings: icon = "account-types_savings"; break; case MyMoneyAccount::AssetLoan: case MyMoneyAccount::Loan: icon = "account-types_loan"; break; case MyMoneyAccount::CreditCard: icon = "account-types_credit-card"; break; case MyMoneyAccount::Asset: icon = "account-types_asset"; break; case MyMoneyAccount::Cash: icon = "account-types_cash"; break; case MyMoneyAccount::Income: icon = "account-types_income"; break; case MyMoneyAccount::Expense: icon = "account-types_expense"; break; case MyMoneyAccount::Equity: icon = "account"; break; } TQPixmap result = DesktopIcon(icon, size); if(isClosed()) { TQPixmap ovly = DesktopIcon("account-types_closed", size); bitBlt(TQT_TQPAINTDEVICE(&result), 0, 0, TQT_TQPAINTDEVICE(&ovly), 0, 0, ovly.width(), ovly.height(), TQt::CopyROP, false); } else if(reconcileFlag) { TQPixmap ovly = DesktopIcon("account-types_reconcile.png", size); bitBlt(TQT_TQPAINTDEVICE(&result), 0, 0, TQT_TQPAINTDEVICE(&ovly), 0, 0, ovly.width(), ovly.height(), TQt::CopyROP, false); } else if(!onlineBankingSettings().value("provider").isEmpty()) { TQPixmap ovly = DesktopIcon("account-types_online.png", size); bitBlt(TQT_TQPAINTDEVICE(&result), 0, 0, TQT_TQPAINTDEVICE(&ovly), 0, 0, ovly.width(), ovly.height(), TQt::CopyROP, false); } return result; } TQString MyMoneyAccount::accountTypeToString(const MyMoneyAccount::accountTypeE accountType) { TQString returnString; switch (accountType) { case MyMoneyAccount::Checkings: returnString = i18n("Checking"); break; case MyMoneyAccount::Savings: returnString = i18n("Savings"); break; case MyMoneyAccount::CreditCard: returnString = i18n("Credit Card"); break; case MyMoneyAccount::Cash: returnString = i18n("Cash"); break; case MyMoneyAccount::Loan: returnString = i18n("Loan"); break; case MyMoneyAccount::CertificateDep: returnString = i18n("Certificate of Deposit"); break; case MyMoneyAccount::Investment: returnString = i18n("Investment"); break; case MyMoneyAccount::MoneyMarket: returnString = i18n("Money Market"); break; case MyMoneyAccount::Asset: returnString = i18n("Asset"); break; case MyMoneyAccount::Liability: returnString = i18n("Liability"); break; case MyMoneyAccount::Currency: returnString = i18n("Currency"); break; case MyMoneyAccount::Income: returnString = i18n("Income"); break; case MyMoneyAccount::Expense: returnString = i18n("Expense"); break; case MyMoneyAccount::AssetLoan: returnString = i18n("Investment Loan"); break; case MyMoneyAccount::Stock: returnString = i18n("Stock"); break; case MyMoneyAccount::Equity: returnString = i18n("Equity"); break; default: returnString = i18n("Unknown"); } return returnString; }