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.
1945 lines
57 KiB
1945 lines
57 KiB
/***************************************************************************
|
|
mymoneyseqaccessmgr.cpp
|
|
-------------------
|
|
begin : Sun May 5 2002
|
|
copyright : (C) 2000-2002 by Michael Edwardes
|
|
2002 Thomas Baumgart
|
|
email : mte@users.sourceforge.net
|
|
Thomas Baumgart <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. *
|
|
* *
|
|
***************************************************************************/
|
|
|
|
#include <typeinfo>
|
|
#include "mymoneyseqaccessmgr.h"
|
|
#include "../mymoneytransactionfilter.h"
|
|
#include "../mymoneycategory.h"
|
|
|
|
#define TRY try {
|
|
#define CATCH } catch (MyMoneyException *e) {
|
|
#define PASS } catch (MyMoneyException *e) { throw; }
|
|
|
|
bool MyMoneyBalanceCacheItem::operator ==(const MyMoneyBalanceCacheItem & right) const
|
|
{
|
|
return ((balance == right.balance)
|
|
&& (valid == right.valid));
|
|
}
|
|
|
|
MyMoneySeqAccessMgr::MyMoneySeqAccessMgr()
|
|
{
|
|
m_nextAccountID = 0;
|
|
m_nextInstitutionID = 0;
|
|
m_nextTransactionID = 0;
|
|
m_nextPayeeID = 0;
|
|
m_nextScheduleID = 0;
|
|
m_nextSecurityID = 0;
|
|
m_nextReportID = 0;
|
|
m_nextBudgetID = 0;
|
|
m_user = MyMoneyPayee();
|
|
m_dirty = false;
|
|
m_creationDate = TQDate::tqcurrentDate();
|
|
|
|
// setup standard accounts
|
|
MyMoneyAccount acc_l;
|
|
acc_l.setAccountType(MyMoneyAccount::Liability);
|
|
acc_l.setName("Liability");
|
|
MyMoneyAccount liability(STD_ACC_LIABILITY, acc_l);
|
|
|
|
MyMoneyAccount acc_a;
|
|
acc_a.setAccountType(MyMoneyAccount::Asset);
|
|
acc_a.setName("Asset");
|
|
MyMoneyAccount asset(STD_ACC_ASSET, acc_a);
|
|
|
|
MyMoneyAccount acc_e;
|
|
acc_e.setAccountType(MyMoneyAccount::Expense);
|
|
acc_e.setName("Expense");
|
|
MyMoneyAccount expense(STD_ACC_EXPENSE, acc_e);
|
|
|
|
MyMoneyAccount acc_i;
|
|
acc_i.setAccountType(MyMoneyAccount::Income);
|
|
acc_i.setName("Income");
|
|
MyMoneyAccount income(STD_ACC_INCOME, acc_i);
|
|
|
|
MyMoneyAccount acc_q;
|
|
acc_q.setAccountType(MyMoneyAccount::Equity);
|
|
acc_q.setName("Equity");
|
|
MyMoneyAccount equity(STD_ACC_ETQUITY, acc_q);
|
|
|
|
TQMap<TQString, MyMoneyAccount> map;
|
|
map[STD_ACC_ASSET] = asset;
|
|
map[STD_ACC_LIABILITY] = liability;
|
|
map[STD_ACC_INCOME] = income;
|
|
map[STD_ACC_EXPENSE] = expense;
|
|
map[STD_ACC_ETQUITY] = equity;
|
|
|
|
// load account list with inital accounts
|
|
m_accountList = map;
|
|
|
|
MyMoneyBalanceCacheItem balance;
|
|
|
|
m_balanceCache.clear();
|
|
m_balanceCache[STD_ACC_LIABILITY] = balance;
|
|
m_balanceCache[STD_ACC_ASSET] = balance;
|
|
m_balanceCache[STD_ACC_EXPENSE] = balance;
|
|
m_balanceCache[STD_ACC_INCOME] = balance;
|
|
m_balanceCache[STD_ACC_ETQUITY] = balance;
|
|
|
|
// initialize for file fixes (see kmymoneyview.cpp)
|
|
m_currentFixVersion = 2;
|
|
m_fileFixVersion = 0; // default value if no fix-version in file
|
|
m_transactionListFull = false;
|
|
}
|
|
|
|
MyMoneySeqAccessMgr::~MyMoneySeqAccessMgr()
|
|
{
|
|
}
|
|
|
|
MyMoneySeqAccessMgr const * MyMoneySeqAccessMgr::duplicate(void)
|
|
{
|
|
MyMoneySeqAccessMgr* that = new MyMoneySeqAccessMgr();
|
|
*that = *this;
|
|
return that;
|
|
}
|
|
/**
|
|
* This method is used to get a SQL reader for subsequent database access
|
|
*/
|
|
KSharedPtr <MyMoneyStorageSql> MyMoneySeqAccessMgr::connectToDatabase
|
|
(const KURL& /*url*/) {
|
|
return 0;
|
|
}
|
|
|
|
bool MyMoneySeqAccessMgr::isStandardAccount(const TQString& id) const
|
|
{
|
|
return id == STD_ACC_LIABILITY
|
|
|| id == STD_ACC_ASSET
|
|
|| id == STD_ACC_EXPENSE
|
|
|| id == STD_ACC_INCOME
|
|
|| id == STD_ACC_ETQUITY;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::setAccountName(const TQString& id, const TQString& name)
|
|
{
|
|
if(!isStandardAccount(id))
|
|
throw new MYMONEYEXCEPTION("Only standard accounts can be modified using setAccountName()");
|
|
|
|
MyMoneyAccount acc = m_accountList[id];
|
|
acc.setName(name);
|
|
m_accountList.modify(acc.id(), acc);
|
|
}
|
|
|
|
const MyMoneyAccount MyMoneySeqAccessMgr::account(const TQString& id) const
|
|
{
|
|
// locate the account and if present, return it's data
|
|
if(m_accountList.tqfind(id) != m_accountList.end())
|
|
return m_accountList[id];
|
|
|
|
// throw an exception, if it does not exist
|
|
TQString msg = "Unknown account id '" + id + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::accountList(TQValueList<MyMoneyAccount>& list) const
|
|
{
|
|
TQMap<TQString, MyMoneyAccount>::ConstIterator it;
|
|
for(it = m_accountList.begin(); it != m_accountList.end(); ++it) {
|
|
if(!isStandardAccount((*it).id())) {
|
|
list.append(*it);
|
|
}
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::addAccount(MyMoneyAccount& account)
|
|
{
|
|
// create the account.
|
|
MyMoneyAccount newAccount(nextAccountID(), account);
|
|
m_accountList.insert(newAccount.id(), newAccount);
|
|
|
|
account = newAccount;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::addPayee(MyMoneyPayee& payee)
|
|
{
|
|
// create the payee
|
|
MyMoneyPayee newPayee(nextPayeeID(), payee);
|
|
m_payeeList.insert(newPayee.id(), newPayee);
|
|
payee = newPayee;
|
|
}
|
|
|
|
const MyMoneyPayee MyMoneySeqAccessMgr::payee(const TQString& id) const
|
|
{
|
|
TQMap<TQString, MyMoneyPayee>::ConstIterator it;
|
|
it = m_payeeList.tqfind(id);
|
|
if(it == m_payeeList.end())
|
|
throw new MYMONEYEXCEPTION("Unknown payee '" + id + "'");
|
|
|
|
return *it;
|
|
}
|
|
|
|
const MyMoneyPayee MyMoneySeqAccessMgr::payeeByName(const TQString& payee) const
|
|
{
|
|
if(payee.isEmpty())
|
|
return MyMoneyPayee::null;
|
|
|
|
TQMap<TQString, MyMoneyPayee>::ConstIterator it_p;
|
|
|
|
for(it_p = m_payeeList.begin(); it_p != m_payeeList.end(); ++it_p) {
|
|
if((*it_p).name() == payee) {
|
|
return *it_p;
|
|
}
|
|
}
|
|
|
|
throw new MYMONEYEXCEPTION("Unknown payee '" + payee + "'");
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::modifyPayee(const MyMoneyPayee& payee)
|
|
{
|
|
TQMap<TQString, MyMoneyPayee>::ConstIterator it;
|
|
|
|
it = m_payeeList.tqfind(payee.id());
|
|
if(it == m_payeeList.end()) {
|
|
TQString msg = "Unknown payee '" + payee.id() + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
m_payeeList.modify((*it).id(), payee);
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::removePayee(const MyMoneyPayee& payee)
|
|
{
|
|
TQMap<TQString, MyMoneyTransaction>::ConstIterator it_t;
|
|
TQMap<TQString, MyMoneySchedule>::ConstIterator it_s;
|
|
TQMap<TQString, MyMoneyPayee>::ConstIterator it_p;
|
|
|
|
it_p = m_payeeList.tqfind(payee.id());
|
|
if(it_p == m_payeeList.end()) {
|
|
TQString msg = "Unknown payee '" + payee.id() + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
// scan all transactions to check if the payee is still referenced
|
|
for(it_t = m_transactionList.begin(); it_t != m_transactionList.end(); ++it_t) {
|
|
if((*it_t).hasReferenceTo(payee.id())) {
|
|
throw new MYMONEYEXCEPTION(TQString("Cannot remove payee that is still referenced to a %1").tqarg("transaction"));
|
|
}
|
|
}
|
|
|
|
// check referential integrity in schedules
|
|
for(it_s = m_scheduleList.begin(); it_s != m_scheduleList.end(); ++it_s) {
|
|
if((*it_s).hasReferenceTo(payee.id())) {
|
|
throw new MYMONEYEXCEPTION(TQString("Cannot remove payee that is still referenced to a %1").tqarg("schedule"));
|
|
}
|
|
}
|
|
|
|
// remove any reference to report and/or budget
|
|
removeReferences(payee.id());
|
|
|
|
m_payeeList.remove((*it_p).id());
|
|
}
|
|
|
|
const TQValueList<MyMoneyPayee> MyMoneySeqAccessMgr::payeeList(void) const
|
|
{
|
|
return m_payeeList.values();
|
|
}
|
|
|
|
|
|
void MyMoneySeqAccessMgr::addAccount(MyMoneyAccount& tqparent, MyMoneyAccount& account)
|
|
{
|
|
TQMap<TQString, MyMoneyAccount>::ConstIterator theParent;
|
|
TQMap<TQString, MyMoneyAccount>::ConstIterator theChild;
|
|
|
|
theParent = m_accountList.tqfind(tqparent.id());
|
|
if(theParent == m_accountList.end()) {
|
|
TQString msg = "Unknown tqparent account '";
|
|
msg += tqparent.id() + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
theChild = m_accountList.tqfind(account.id());
|
|
if(theChild == m_accountList.end()) {
|
|
TQString msg = "Unknown child account '";
|
|
msg += account.id() + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
MyMoneyAccount acc = *theParent;
|
|
acc.addAccountId(account.id());
|
|
m_accountList.modify(acc.id(), acc);
|
|
tqparent = acc;
|
|
|
|
acc = *theChild;
|
|
acc.setParentAccountId(tqparent.id());
|
|
m_accountList.modify(acc.id(), acc);
|
|
account = acc;
|
|
|
|
MyMoneyBalanceCacheItem balance;
|
|
m_balanceCache[account.id()] = balance;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::addInstitution(MyMoneyInstitution& institution)
|
|
{
|
|
MyMoneyInstitution newInstitution(nextInstitutionID(), institution);
|
|
|
|
m_institutionList.insert(newInstitution.id(), newInstitution);
|
|
|
|
// return new data
|
|
institution = newInstitution;
|
|
}
|
|
|
|
unsigned int MyMoneySeqAccessMgr::transactionCount(const TQString& account) const
|
|
{
|
|
unsigned int cnt = 0;
|
|
|
|
if(account.length() == 0) {
|
|
cnt = m_transactionList.count();
|
|
|
|
} else {
|
|
TQMap<TQString, MyMoneyTransaction>::ConstIterator it_t;
|
|
TQValueList<MyMoneySplit>::ConstIterator it_s;
|
|
|
|
// scan all transactions
|
|
for(it_t = m_transactionList.begin(); it_t != m_transactionList.end(); ++it_t) {
|
|
|
|
// scan all splits of this transaction
|
|
for(it_s = (*it_t).splits().begin(); it_s != (*it_t).splits().end(); ++it_s) {
|
|
// is it a split in our account?
|
|
if((*it_s).accountId() == account) {
|
|
// since a transaction can only have one split referencing
|
|
// each account, we're done with the splits here!
|
|
break;
|
|
}
|
|
}
|
|
// if no split contains the account id, continue with the
|
|
// next transaction
|
|
if(it_s == (*it_t).splits().end())
|
|
continue;
|
|
|
|
// otherwise count it
|
|
++cnt;
|
|
}
|
|
}
|
|
return cnt;
|
|
}
|
|
|
|
const TQMap<TQString, unsigned long> MyMoneySeqAccessMgr::transactionCountMap(void) const
|
|
{
|
|
TQMap<TQString, unsigned long> map;
|
|
TQMap<TQString, MyMoneyTransaction>::ConstIterator it_t;
|
|
TQValueList<MyMoneySplit>::ConstIterator it_s;
|
|
|
|
// scan all transactions
|
|
for(it_t = m_transactionList.begin(); it_t != m_transactionList.end(); ++it_t) {
|
|
// scan all splits of this transaction
|
|
for(it_s = (*it_t).splits().begin(); it_s != (*it_t).splits().end(); ++it_s) {
|
|
map[(*it_s).accountId()]++;
|
|
}
|
|
}
|
|
return map;
|
|
}
|
|
|
|
unsigned int MyMoneySeqAccessMgr::institutionCount(void) const
|
|
{
|
|
return m_institutionList.count();
|
|
}
|
|
|
|
unsigned int MyMoneySeqAccessMgr::accountCount(void) const
|
|
{
|
|
return m_accountList.count();
|
|
}
|
|
|
|
TQString MyMoneySeqAccessMgr::nextPayeeID(void)
|
|
{
|
|
TQString id;
|
|
id.setNum(++m_nextPayeeID);
|
|
id = "P" + id.rightJustify(PAYEE_ID_SIZE, '0');
|
|
return id;
|
|
}
|
|
|
|
TQString MyMoneySeqAccessMgr::nextInstitutionID(void)
|
|
{
|
|
TQString id;
|
|
id.setNum(++m_nextInstitutionID);
|
|
id = "I" + id.rightJustify(INSTITUTION_ID_SIZE, '0');
|
|
return id;
|
|
}
|
|
|
|
TQString MyMoneySeqAccessMgr::nextAccountID(void)
|
|
{
|
|
TQString id;
|
|
id.setNum(++m_nextAccountID);
|
|
id = "A" + id.rightJustify(ACCOUNT_ID_SIZE, '0');
|
|
return id;
|
|
}
|
|
|
|
TQString MyMoneySeqAccessMgr::nextTransactionID(void)
|
|
{
|
|
TQString id;
|
|
id.setNum(++m_nextTransactionID);
|
|
id = "T" + id.rightJustify(TRANSACTION_ID_SIZE, '0');
|
|
return id;
|
|
}
|
|
|
|
TQString MyMoneySeqAccessMgr::nextScheduleID(void)
|
|
{
|
|
TQString id;
|
|
id.setNum(++m_nextScheduleID);
|
|
id = "SCH" + id.rightJustify(SCHEDULE_ID_SIZE, '0');
|
|
return id;
|
|
}
|
|
|
|
TQString MyMoneySeqAccessMgr::nextSecurityID(void)
|
|
{
|
|
TQString id;
|
|
id.setNum(++m_nextSecurityID);
|
|
id = "E" + id.rightJustify(SECURITY_ID_SIZE, '0');
|
|
return id;
|
|
}
|
|
|
|
|
|
void MyMoneySeqAccessMgr::addTransaction(MyMoneyTransaction& transaction, const bool skipAccountUpdate)
|
|
{
|
|
// perform some checks to see that the transaction stuff is OK. For
|
|
// now we assume that
|
|
// * no ids are assigned
|
|
// * the date valid (must not be empty)
|
|
// * the referenced accounts in the splits exist
|
|
|
|
// first perform all the checks
|
|
if(!transaction.id().isEmpty())
|
|
throw new MYMONEYEXCEPTION("transaction already contains an id");
|
|
if(!transaction.postDate().isValid())
|
|
throw new MYMONEYEXCEPTION("invalid post date");
|
|
|
|
// now check the splits
|
|
TQValueList<MyMoneySplit>::ConstIterator it_s;
|
|
for(it_s = transaction.splits().begin(); it_s != transaction.splits().end(); ++it_s) {
|
|
// the following lines will throw an exception if the
|
|
// account or payee do not exist
|
|
account((*it_s).accountId());
|
|
if(!(*it_s).payeeId().isEmpty())
|
|
payee((*it_s).payeeId());
|
|
}
|
|
|
|
MyMoneyTransaction newTransaction(nextTransactionID(), transaction);
|
|
TQString key = newTransaction.uniqueSortKey();
|
|
|
|
m_transactionList.insert(key, newTransaction);
|
|
m_transactionKeys.insert(newTransaction.id(), key);
|
|
|
|
transaction = newTransaction;
|
|
|
|
// adjust the balance of all affected accounts
|
|
for(it_s = transaction.splits().begin(); it_s != transaction.splits().end(); ++it_s) {
|
|
MyMoneyAccount acc = m_accountList[(*it_s).accountId()];
|
|
acc.adjustBalance(*it_s);
|
|
if(!skipAccountUpdate) {
|
|
acc.touch();
|
|
tqinvalidateBalanceCache(acc.id());
|
|
}
|
|
m_accountList.modify(acc.id(), acc);
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::touch(void)
|
|
{
|
|
m_dirty = true;
|
|
m_lastModificationDate = TQDate::tqcurrentDate();
|
|
}
|
|
|
|
bool MyMoneySeqAccessMgr::hasActiveSplits(const TQString& id) const
|
|
{
|
|
TQMap<TQString, MyMoneyTransaction>::ConstIterator it;
|
|
|
|
for(it = m_transactionList.begin(); it != m_transactionList.end(); ++it) {
|
|
if((*it).accountReferenced(id)) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
const MyMoneyInstitution MyMoneySeqAccessMgr::institution(const TQString& id) const
|
|
{
|
|
TQMap<TQString, MyMoneyInstitution>::ConstIterator pos;
|
|
|
|
pos = m_institutionList.tqfind(id);
|
|
if(pos != m_institutionList.end())
|
|
return *pos;
|
|
throw new MYMONEYEXCEPTION("unknown institution");
|
|
}
|
|
|
|
const TQValueList<MyMoneyInstitution> MyMoneySeqAccessMgr::institutionList(void) const
|
|
{
|
|
return m_institutionList.values();
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::modifyAccount(const MyMoneyAccount& account, const bool skipCheck)
|
|
{
|
|
TQMap<TQString, MyMoneyAccount>::ConstIterator pos;
|
|
|
|
// locate the account in the file global pool
|
|
pos = m_accountList.tqfind(account.id());
|
|
if(pos != m_accountList.end()) {
|
|
// check if the new info is based on the old one.
|
|
// this is the case, when the file and the id
|
|
// as well as the type are equal.
|
|
if((((*pos).tqparentAccountId() == account.tqparentAccountId())
|
|
&& ((*pos).accountType() == account.accountType()))
|
|
|| (skipCheck == true)) {
|
|
// make sure that all the referenced objects exist
|
|
if(!account.institutionId().isEmpty())
|
|
institution(account.institutionId());
|
|
|
|
TQValueList<TQString>::ConstIterator it_a;
|
|
for(it_a = account.accountList().begin(); it_a != account.accountList().end(); ++it_a) {
|
|
this->account(*it_a);
|
|
}
|
|
|
|
// update information in account list
|
|
m_accountList.modify(account.id(), account);
|
|
|
|
// tqinvalidate cached balance
|
|
tqinvalidateBalanceCache(account.id());
|
|
|
|
} else
|
|
throw new MYMONEYEXCEPTION("Invalid information for update");
|
|
|
|
} else
|
|
throw new MYMONEYEXCEPTION("Unknown account id");
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::modifyInstitution(const MyMoneyInstitution& institution)
|
|
{
|
|
TQMap<TQString, MyMoneyInstitution>::ConstIterator pos;
|
|
|
|
// locate the institution in the file global pool
|
|
pos = m_institutionList.tqfind(institution.id());
|
|
if(pos != m_institutionList.end()) {
|
|
m_institutionList.modify(institution.id(), institution);
|
|
|
|
} else
|
|
throw new MYMONEYEXCEPTION("unknown institution");
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::modifyTransaction(const MyMoneyTransaction& transaction)
|
|
{
|
|
// perform some checks to see that the transaction stuff is OK. For
|
|
// now we assume that
|
|
// * ids are assigned
|
|
// * the pointer to the MyMoneyFile object is not 0
|
|
// * the date valid (must not be empty)
|
|
// * the splits must have valid account ids
|
|
|
|
// first perform all the checks
|
|
if(transaction.id().isEmpty()
|
|
// || transaction.file() != this
|
|
|| !transaction.postDate().isValid())
|
|
throw new MYMONEYEXCEPTION("invalid transaction to be modified");
|
|
|
|
// now check the splits
|
|
TQValueList<MyMoneySplit>::ConstIterator it_s;
|
|
for(it_s = transaction.splits().begin(); it_s != transaction.splits().end(); ++it_s) {
|
|
// the following lines will throw an exception if the
|
|
// account or payee do not exist
|
|
account((*it_s).accountId());
|
|
if(!(*it_s).payeeId().isEmpty())
|
|
payee((*it_s).payeeId());
|
|
}
|
|
|
|
// new data seems to be ok. find old version of transaction
|
|
// in our pool. Throw exception if unknown.
|
|
if(!m_transactionKeys.tqcontains(transaction.id()))
|
|
throw new MYMONEYEXCEPTION("invalid transaction id");
|
|
|
|
TQString oldKey = m_transactionKeys[transaction.id()];
|
|
if(!m_transactionList.tqcontains(oldKey))
|
|
throw new MYMONEYEXCEPTION("invalid transaction key");
|
|
|
|
TQMap<TQString, MyMoneyTransaction>::ConstIterator it_t;
|
|
|
|
it_t = m_transactionList.tqfind(oldKey);
|
|
if(it_t == m_transactionList.end())
|
|
throw new MYMONEYEXCEPTION("invalid transaction key");
|
|
|
|
// adjust account balances
|
|
for(it_s = (*it_t).splits().begin(); it_s != (*it_t).splits().end(); ++it_s) {
|
|
MyMoneyAccount acc = m_accountList[(*it_s).accountId()];
|
|
acc.adjustBalance(*it_s, true); // reverse the adjust operation (reverse = true)
|
|
acc.touch();
|
|
tqinvalidateBalanceCache(acc.id());
|
|
m_accountList.modify(acc.id(), acc);
|
|
}
|
|
for(it_s = transaction.splits().begin(); it_s != transaction.splits().end(); ++it_s) {
|
|
MyMoneyAccount acc = m_accountList[(*it_s).accountId()];
|
|
acc.adjustBalance(*it_s);
|
|
acc.touch();
|
|
tqinvalidateBalanceCache(acc.id());
|
|
m_accountList.modify(acc.id(), acc);
|
|
}
|
|
|
|
// remove old transaction from lists
|
|
m_transactionList.remove(oldKey);
|
|
|
|
// add new transaction to lists
|
|
TQString newKey = transaction.uniqueSortKey();
|
|
m_transactionList.insert(newKey, transaction);
|
|
m_transactionKeys.modify(transaction.id(), newKey);
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::reparentAccount(MyMoneyAccount &account, MyMoneyAccount& tqparent)
|
|
{
|
|
reparentAccount(account, tqparent, true);
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::reparentAccount(MyMoneyAccount &account, MyMoneyAccount& tqparent, const bool /* sendNotification */)
|
|
{
|
|
TQMap<TQString, MyMoneyAccount>::ConstIterator oldParent;
|
|
TQMap<TQString, MyMoneyAccount>::ConstIterator newParent;
|
|
TQMap<TQString, MyMoneyAccount>::ConstIterator childAccount;
|
|
|
|
// verify that accounts exist. If one does not,
|
|
// an exception is thrown
|
|
MyMoneySeqAccessMgr::account(account.id());
|
|
MyMoneySeqAccessMgr::account(tqparent.id());
|
|
if(!account.tqparentAccountId().isEmpty()) {
|
|
MyMoneySeqAccessMgr::account(account.tqparentAccountId());
|
|
oldParent = m_accountList.tqfind(account.tqparentAccountId());
|
|
}
|
|
|
|
if(account.accountType() == MyMoneyAccount::Stock && tqparent.accountType() != MyMoneyAccount::Investment)
|
|
throw new MYMONEYEXCEPTION("Cannot move a stock acocunt into a non-investment account");
|
|
|
|
newParent = m_accountList.tqfind(tqparent.id());
|
|
childAccount = m_accountList.tqfind(account.id());
|
|
|
|
MyMoneyAccount acc;
|
|
if(!account.tqparentAccountId().isEmpty()) {
|
|
acc = (*oldParent);
|
|
acc.removeAccountId(account.id());
|
|
m_accountList.modify(acc.id(), acc);
|
|
}
|
|
|
|
tqparent = (*newParent);
|
|
tqparent.addAccountId(account.id());
|
|
m_accountList.modify(tqparent.id(), tqparent);
|
|
|
|
account = (*childAccount);
|
|
account.setParentAccountId(tqparent.id());
|
|
m_accountList.modify(account.id(), account);
|
|
|
|
#if 0
|
|
// make sure the type is the same as the new tqparent. This does not work for stock and investment
|
|
if(account.accountType() != MyMoneyAccount::Stock && account.accountType() != MyMoneyAccount::Investment)
|
|
(*childAccount).setAccountType((*newParent).accountType());
|
|
#endif
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::removeTransaction(const MyMoneyTransaction& transaction)
|
|
{
|
|
// first perform all the checks
|
|
if(transaction.id().isEmpty())
|
|
throw new MYMONEYEXCEPTION("invalid transaction to be deleted");
|
|
|
|
TQMap<TQString, TQString>::ConstIterator it_k;
|
|
TQMap<TQString, MyMoneyTransaction>::ConstIterator it_t;
|
|
|
|
it_k = m_transactionKeys.tqfind(transaction.id());
|
|
if(it_k == m_transactionKeys.end())
|
|
throw new MYMONEYEXCEPTION("invalid transaction to be deleted");
|
|
|
|
it_t = m_transactionList.tqfind(*it_k);
|
|
if(it_t == m_transactionList.end())
|
|
throw new MYMONEYEXCEPTION("invalid transaction key");
|
|
|
|
TQValueList<MyMoneySplit>::ConstIterator it_s;
|
|
|
|
// scan the splits and collect all accounts that need
|
|
// to be updated after the removal of this transaction
|
|
for(it_s = (*it_t).splits().begin(); it_s != (*it_t).splits().end(); ++it_s) {
|
|
MyMoneyAccount acc = m_accountList[(*it_s).accountId()];
|
|
acc.adjustBalance(*it_s, true); // reverse = true
|
|
acc.touch();
|
|
m_accountList.modify(acc.id(), acc);
|
|
tqinvalidateBalanceCache(acc.id());
|
|
}
|
|
|
|
// FIXME: check if any split is frozen and throw exception
|
|
|
|
// remove the transaction from the two lists
|
|
m_transactionList.remove(*it_k);
|
|
m_transactionKeys.remove(transaction.id());
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::removeAccount(const MyMoneyAccount& account)
|
|
{
|
|
MyMoneyAccount tqparent;
|
|
|
|
// check that the account and it's tqparent exist
|
|
// this will throw an exception if the id is unknown
|
|
MyMoneySeqAccessMgr::account(account.id());
|
|
tqparent = MyMoneySeqAccessMgr::account(account.tqparentAccountId());
|
|
|
|
// check that it's not one of the standard account groups
|
|
if(isStandardAccount(account.id()))
|
|
throw new MYMONEYEXCEPTION("Unable to remove the standard account groups");
|
|
|
|
if(hasActiveSplits(account.id())) {
|
|
throw new MYMONEYEXCEPTION("Unable to remove account with active splits");
|
|
}
|
|
|
|
// re-tqparent all sub-ordinate accounts to the tqparent of the account
|
|
// to be deleted. First round check that all accounts exist, second
|
|
// round do the re-tqparenting.
|
|
TQStringList::ConstIterator it;
|
|
for(it = account.accountList().begin(); it != account.accountList().end(); ++it) {
|
|
MyMoneySeqAccessMgr::account(*it);
|
|
}
|
|
|
|
// if one of the accounts did not exist, an exception had been
|
|
// thrown and we would not make it until here.
|
|
|
|
TQMap<TQString, MyMoneyAccount>::ConstIterator it_a;
|
|
TQMap<TQString, MyMoneyAccount>::ConstIterator it_p;
|
|
|
|
// locate the account in the file global pool
|
|
|
|
it_a = m_accountList.tqfind(account.id());
|
|
if(it_a == m_accountList.end())
|
|
throw new MYMONEYEXCEPTION("Internal error: account not found in list");
|
|
|
|
it_p = m_accountList.tqfind(tqparent.id());
|
|
if(it_p == m_accountList.end())
|
|
throw new MYMONEYEXCEPTION("Internal error: tqparent account not found in list");
|
|
|
|
if(!account.institutionId().isEmpty())
|
|
throw new MYMONEYEXCEPTION("Cannot remove account still attached to an institution");
|
|
|
|
removeReferences(account.id());
|
|
|
|
// FIXME: check referential integrity for the account to be removed
|
|
|
|
// check if the new info is based on the old one.
|
|
// this is the case, when the file and the id
|
|
// as well as the type are equal.
|
|
if((*it_a).id() == account.id()
|
|
&& (*it_a).accountType() == account.accountType()) {
|
|
|
|
// second round over sub-ordinate accounts: do re-tqparenting
|
|
// but only if the list contains at least one entry
|
|
// FIXME: move this logic to MyMoneyFile
|
|
if((*it_a).accountList().count() > 0) {
|
|
while((*it_a).accountList().count() > 0) {
|
|
it = (*it_a).accountList().begin();
|
|
MyMoneyAccount acc(MyMoneySeqAccessMgr::account(*it));
|
|
reparentAccount(acc, tqparent, false);
|
|
}
|
|
}
|
|
// remove account from tqparent's list
|
|
tqparent.removeAccountId(account.id());
|
|
m_accountList.modify(tqparent.id(), tqparent);
|
|
|
|
// remove account from the global account pool
|
|
m_accountList.remove(account.id());
|
|
|
|
// remove from balance list
|
|
m_balanceCache.remove(account.id());
|
|
tqinvalidateBalanceCache(tqparent.id());
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::removeInstitution(const MyMoneyInstitution& institution)
|
|
{
|
|
TQMap<TQString, MyMoneyInstitution>::ConstIterator it_i;
|
|
|
|
it_i = m_institutionList.tqfind(institution.id());
|
|
if(it_i != m_institutionList.end()) {
|
|
m_institutionList.remove(institution.id());
|
|
|
|
} else
|
|
throw new MYMONEYEXCEPTION("invalid institution");
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::transactionList(TQValueList<MyMoneyTransaction>& list, MyMoneyTransactionFilter& filter) const
|
|
{
|
|
list.clear();
|
|
|
|
TQMap<TQString, MyMoneyTransaction>::ConstIterator it_t;
|
|
|
|
for(it_t = m_transactionList.begin(); it_t != m_transactionList.end(); ++it_t) {
|
|
// This code is used now. It adds the transaction to the list for
|
|
// each matching split exactly once. This allows to show information
|
|
// about different splits in the same register view (e.g. search result)
|
|
//
|
|
// I have no idea, if this has some impact on the functionality. So far,
|
|
// I could not see it. (ipwizard 9/5/2003)
|
|
if(filter.match(*it_t)) {
|
|
unsigned int cnt = filter.matchingSplits().count();
|
|
if(cnt > 1) {
|
|
for(unsigned i=0; i < cnt; ++i)
|
|
list.append(*it_t);
|
|
} else {
|
|
list.append(*it_t);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::transactionList(TQValueList< TQPair<MyMoneyTransaction, MyMoneySplit> >& list, MyMoneyTransactionFilter& filter) const
|
|
{
|
|
list.clear();
|
|
|
|
TQMap<TQString, MyMoneyTransaction>::ConstIterator it_t;
|
|
|
|
for(it_t = m_transactionList.begin(); it_t != m_transactionList.end(); ++it_t) {
|
|
if(filter.match(*it_t)) {
|
|
TQValueList<MyMoneySplit>::const_iterator it_s;
|
|
for(it_s = filter.matchingSplits().begin(); it_s != filter.matchingSplits().end(); ++it_s) {
|
|
list.append(tqMakePair(*it_t, *it_s));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const TQValueList<MyMoneyTransaction> MyMoneySeqAccessMgr::transactionList(MyMoneyTransactionFilter& filter) const
|
|
{
|
|
TQValueList<MyMoneyTransaction> list;
|
|
transactionList(list, filter);
|
|
return list;
|
|
}
|
|
|
|
const MyMoneyTransaction MyMoneySeqAccessMgr::transaction(const TQString& id) const
|
|
{
|
|
// get the full key of this transaction, throw exception
|
|
// if it's invalid (unknown)
|
|
if(!m_transactionKeys.tqcontains(id)) {
|
|
TQString msg = TQString("Invalid transaction id '%1'").tqarg(id);
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
// check if this key is in the list, throw exception if not
|
|
TQString key = m_transactionKeys[id];
|
|
if(!m_transactionList.tqcontains(key)) {
|
|
TQString msg = TQString("Invalid transaction key '%1'").tqarg(key);
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
return m_transactionList[key];
|
|
}
|
|
|
|
const MyMoneyTransaction MyMoneySeqAccessMgr::transaction(const TQString& account, const int idx) const
|
|
{
|
|
/* removed with MyMoneyAccount::Transaction
|
|
TQMap<TQString, MyMoneyAccount>::ConstIterator acc;
|
|
|
|
// find account object in list, throw exception if unknown
|
|
acc = m_accountList.tqfind(account);
|
|
if(acc == m_accountList.end())
|
|
throw new MYMONEYEXCEPTION("unknown account id");
|
|
|
|
// get the transaction info from the account
|
|
MyMoneyAccount::Transaction t = (*acc).transaction(idx);
|
|
|
|
// return the transaction, throw exception if not found
|
|
return transaction(t.transactionID());
|
|
*/
|
|
|
|
// new implementation if the above code does not work anymore
|
|
TQValueList<MyMoneyTransaction> list;
|
|
MyMoneyAccount acc = m_accountList[account];
|
|
MyMoneyTransactionFilter filter;
|
|
|
|
if(acc.accountGroup() == MyMoneyAccount::Income
|
|
|| acc.accountGroup() == MyMoneyAccount::Expense)
|
|
filter.addCategory(account);
|
|
else
|
|
filter.addAccount(account);
|
|
|
|
transactionList(list, filter);
|
|
if(idx < 0 || idx >= static_cast<int> (list.count()))
|
|
throw new MYMONEYEXCEPTION("Unknown idx for transaction");
|
|
|
|
return transaction(list[idx].id());
|
|
}
|
|
|
|
const MyMoneyMoney MyMoneySeqAccessMgr::balance(const TQString& id, const TQDate& date) const
|
|
{
|
|
MyMoneyMoney result(0);
|
|
MyMoneyAccount acc;
|
|
// if (date != TQDate()) qDebug ("request balance for %s at %s", id.data(), date.toString(Qt::ISODate).latin1());
|
|
if(!date.isValid() && account(id).accountType() != MyMoneyAccount::Stock) {
|
|
if(m_accountList.tqfind(id) != m_accountList.end())
|
|
return m_accountList[id].balance();
|
|
return MyMoneyMoney(0);
|
|
}
|
|
if(m_balanceCache[id].valid == false || date != m_balanceCacheDate) {
|
|
TQMap<TQString, MyMoneyMoney> balances;
|
|
TQMap<TQString, MyMoneyMoney>::ConstIterator it_b;
|
|
if (date != m_balanceCacheDate) {
|
|
m_balanceCache.clear();
|
|
m_balanceCacheDate = date;
|
|
}
|
|
|
|
TQValueList<MyMoneyTransaction> list;
|
|
TQValueList<MyMoneyTransaction>::ConstIterator it_t;
|
|
TQValueList<MyMoneySplit>::ConstIterator it_s;
|
|
|
|
MyMoneyTransactionFilter filter;
|
|
filter.setDateFilter(TQDate(), date);
|
|
filter.setReportAllSplits(false);
|
|
transactionList(list, filter);
|
|
|
|
for(it_t = list.begin(); it_t != list.end(); ++it_t) {
|
|
for(it_s = (*it_t).splits().begin(); it_s != (*it_t).splits().end(); ++it_s){
|
|
const TQString& aid = (*it_s).accountId();
|
|
if((*it_s).action() == MyMoneySplit::ActionSplitShares) {
|
|
balances[aid] = balances[aid] * (*it_s).shares();
|
|
} else {
|
|
balances[aid] += (*it_s).shares();
|
|
}
|
|
}
|
|
}
|
|
|
|
// fill the found balances into the cache
|
|
for(it_b = balances.begin(); it_b != balances.end(); ++it_b) {
|
|
MyMoneyBalanceCacheItem balance(*it_b);
|
|
m_balanceCache[it_b.key()] = balance;
|
|
}
|
|
|
|
// fill all accounts w/o transactions to zero
|
|
TQMap<TQString, MyMoneyAccount>::ConstIterator it_a;
|
|
for(it_a = m_accountList.begin(); it_a != m_accountList.end(); ++it_a) {
|
|
if(m_balanceCache[(*it_a).id()].valid == false) {
|
|
MyMoneyBalanceCacheItem balance(MyMoneyMoney(0,1));
|
|
m_balanceCache[(*it_a).id()] = balance;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(m_balanceCache[id].valid == true)
|
|
result = m_balanceCache[id].balance;
|
|
else
|
|
qDebug("Cache mishit should never happen at this point");
|
|
|
|
return result;
|
|
}
|
|
|
|
const MyMoneyMoney MyMoneySeqAccessMgr::totalBalance(const TQString& id, const TQDate& date) const
|
|
{
|
|
TQStringList accounts;
|
|
TQStringList::ConstIterator it_a;
|
|
|
|
MyMoneyMoney result(balance(id, date));
|
|
|
|
accounts = account(id).accountList();
|
|
|
|
for(it_a = accounts.begin(); it_a != accounts.end(); ++it_a) {
|
|
result += totalBalance(*it_a, date);
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/**
|
|
* this was intended to move all splits from one account
|
|
* to another. This somehow is strange to undo because many
|
|
* changes to different objects are made within one single call.
|
|
* I kept the source here but commented it out. If we ever need
|
|
* the functionality, we can turn it back on. BTW: the stuff is untested ;-)
|
|
*/
|
|
/*
|
|
const unsigned int MyMoneyFile::moveSplits(const TQString& oldAccount, const TQString& newAccount)
|
|
{
|
|
TQMap<TQString, MyMoneyTransaction>::Iterator it_t;
|
|
TQValueList<MyMoneySplit>::ConstIterator it_s;
|
|
unsigned int cnt = 0;
|
|
|
|
// scan all transactions
|
|
for(it_t = m_transactionList.begin(); it_t != m_transactionList.end(); ++it_t) {
|
|
// scan all splits of this transaction
|
|
for(it_s = (*it_t).splits().begin(); it_s != (*it_t).splits().end(); ++it_s) {
|
|
// is it a split in our account?
|
|
if((*it_s).account() == oldAccount) {
|
|
MyMoneySplit s = *it_s;
|
|
s.setAccount(newAccount);
|
|
(*it_t).modifySplit(s);
|
|
++cnt;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(cnt != 0) {
|
|
// now update all the accounts that were referenced
|
|
TQMap<TQString, MyMoneyAccount>::Iterator acc;
|
|
acc = m_accountList.tqfind(oldAccount);
|
|
if(acc != m_accountList.end()) {
|
|
(*acc).touch();
|
|
refreshAccountTransactionList(acc);
|
|
}
|
|
acc = m_accountList.tqfind(newAccount);
|
|
if(acc != m_accountList.end()) {
|
|
(*acc).touch();
|
|
refreshAccountTransactionList(acc);
|
|
}
|
|
|
|
// mark file as changed
|
|
m_dirty = true;
|
|
}
|
|
return cnt;
|
|
}
|
|
*/
|
|
|
|
void MyMoneySeqAccessMgr::tqinvalidateBalanceCache(const TQString& id)
|
|
{
|
|
if(!id.isEmpty()) {
|
|
try {
|
|
m_balanceCache[id].valid = false;
|
|
if(!isStandardAccount(id)) {
|
|
tqinvalidateBalanceCache(account(id).tqparentAccountId());
|
|
}
|
|
} catch (MyMoneyException *e) {
|
|
delete e;
|
|
}
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadAccounts(const TQMap<TQString, MyMoneyAccount>& map)
|
|
{
|
|
m_accountList = map;
|
|
|
|
// scan the map to identify the last used id
|
|
TQMap<TQString, MyMoneyAccount>::const_iterator it_a;
|
|
TQString lastId("");
|
|
for(it_a = map.begin(); it_a != map.end(); ++it_a) {
|
|
if(!isStandardAccount((*it_a).id()) && ((*it_a).id() > lastId))
|
|
lastId = (*it_a).id();
|
|
}
|
|
|
|
int pos = lastId.tqfind(TQRegExp("\\d+"), 0);
|
|
if(pos != -1) {
|
|
m_nextAccountID = atol(lastId.mid(pos));
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadTransactions(const TQMap<TQString, MyMoneyTransaction>& map)
|
|
{
|
|
m_transactionList = map;
|
|
|
|
// now fill the key map and
|
|
// identify the last used id
|
|
TQString lastId("");
|
|
TQMap<TQString, TQString> keys;
|
|
TQMap<TQString, MyMoneyTransaction>::ConstIterator it_t;
|
|
for(it_t = map.begin(); it_t != map.end(); ++it_t) {
|
|
keys[(*it_t).id()] = it_t.key();
|
|
if((*it_t).id() > lastId)
|
|
lastId = (*it_t).id();
|
|
}
|
|
m_transactionKeys = keys;
|
|
|
|
|
|
int pos = lastId.tqfind(TQRegExp("\\d+"), 0);
|
|
if(pos != -1) {
|
|
m_nextTransactionID = atol(lastId.mid(pos));
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadInstitutions(const TQMap<TQString, MyMoneyInstitution>& map)
|
|
{
|
|
m_institutionList = map;
|
|
|
|
// scan the map to identify the last used id
|
|
TQMap<TQString, MyMoneyInstitution>::const_iterator it_i;
|
|
TQString lastId("");
|
|
for(it_i = map.begin(); it_i != map.end(); ++it_i) {
|
|
if((*it_i).id() > lastId)
|
|
lastId = (*it_i).id();
|
|
}
|
|
|
|
int pos = lastId.tqfind(TQRegExp("\\d+"), 0);
|
|
if(pos != -1) {
|
|
m_nextInstitutionID = atol(lastId.mid(pos));
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadPayees(const TQMap<TQString, MyMoneyPayee>& map)
|
|
{
|
|
m_payeeList = map;
|
|
|
|
// scan the map to identify the last used id
|
|
TQMap<TQString, MyMoneyPayee>::const_iterator it_p;
|
|
TQString lastId("");
|
|
for(it_p = map.begin(); it_p != map.end(); ++it_p) {
|
|
if((*it_p).id().length() <= PAYEE_ID_SIZE+1) {
|
|
if((*it_p).id() > lastId)
|
|
lastId = (*it_p).id();
|
|
} else {
|
|
}
|
|
}
|
|
|
|
int pos = lastId.tqfind(TQRegExp("\\d+"), 0);
|
|
if(pos != -1) {
|
|
m_nextPayeeID = atol(lastId.mid(pos));
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadSecurities(const TQMap<TQString, MyMoneySecurity>& map)
|
|
{
|
|
m_securitiesList = map;
|
|
|
|
// scan the map to identify the last used id
|
|
TQMap<TQString, MyMoneySecurity>::const_iterator it_s;
|
|
TQString lastId("");
|
|
for(it_s = map.begin(); it_s != map.end(); ++it_s) {
|
|
if((*it_s).id() > lastId)
|
|
lastId = (*it_s).id();
|
|
}
|
|
|
|
int pos = lastId.tqfind(TQRegExp("\\d+"), 0);
|
|
if(pos != -1) {
|
|
m_nextSecurityID = atol(lastId.mid(pos));
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadCurrencies(const TQMap<TQString, MyMoneySecurity>& map)
|
|
{
|
|
m_currencyList = map;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadPrices(const MyMoneyPriceList& list)
|
|
{
|
|
m_priceList = list;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadAccountId(const unsigned long id)
|
|
{
|
|
m_nextAccountID = id;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadTransactionId(const unsigned long id)
|
|
{
|
|
m_nextTransactionID = id;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadPayeeId(const unsigned long id)
|
|
{
|
|
m_nextPayeeID = id;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadInstitutionId(const unsigned long id)
|
|
{
|
|
m_nextInstitutionID = id;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadSecurityId(const unsigned long id)
|
|
{
|
|
m_nextSecurityID = id;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadReportId(const unsigned long id)
|
|
{
|
|
m_nextReportID = id;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadBudgetId(const unsigned long id)
|
|
{
|
|
m_nextBudgetID = id;
|
|
}
|
|
|
|
const TQString MyMoneySeqAccessMgr::value(const TQString& key) const
|
|
{
|
|
return MyMoneyKeyValueContainer::value(key);
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::setValue(const TQString& key, const TQString& val)
|
|
{
|
|
MyMoneyKeyValueContainer::setValue(key, val);
|
|
touch();
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::deletePair(const TQString& key)
|
|
{
|
|
MyMoneyKeyValueContainer::deletePair(key);
|
|
touch();
|
|
}
|
|
|
|
const TQMap<TQString, TQString> MyMoneySeqAccessMgr::pairs(void) const
|
|
{
|
|
return MyMoneyKeyValueContainer::pairs();
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::setPairs(const TQMap<TQString, TQString>& list)
|
|
{
|
|
MyMoneyKeyValueContainer::setPairs(list);
|
|
touch();
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::addSchedule(MyMoneySchedule& sched)
|
|
{
|
|
// first perform all the checks
|
|
if(!sched.id().isEmpty())
|
|
throw new MYMONEYEXCEPTION("schedule already contains an id");
|
|
|
|
// The following will throw an exception when it fails
|
|
sched.validate(false);
|
|
|
|
MyMoneySchedule newSched(nextScheduleID(), sched);
|
|
m_scheduleList.insert(newSched.id(), newSched);
|
|
sched = newSched;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::modifySchedule(const MyMoneySchedule& sched)
|
|
{
|
|
TQMap<TQString, MyMoneySchedule>::ConstIterator it;
|
|
|
|
it = m_scheduleList.tqfind(sched.id());
|
|
if(it == m_scheduleList.end()) {
|
|
TQString msg = "Unknown schedule '" + sched.id() + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
m_scheduleList.modify(sched.id(), sched);
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::removeSchedule(const MyMoneySchedule& sched)
|
|
{
|
|
TQMap<TQString, MyMoneySchedule>::ConstIterator it;
|
|
|
|
it = m_scheduleList.tqfind(sched.id());
|
|
if(it == m_scheduleList.end()) {
|
|
TQString msg = "Unknown schedule '" + sched.id() + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
// FIXME: check referential integrity for loan accounts
|
|
m_scheduleList.remove(sched.id());
|
|
}
|
|
|
|
const MyMoneySchedule MyMoneySeqAccessMgr::schedule(const TQString& id) const
|
|
{
|
|
TQMap<TQString, MyMoneySchedule>::ConstIterator pos;
|
|
|
|
// locate the schedule and if present, return it's data
|
|
pos = m_scheduleList.tqfind(id);
|
|
if(pos != m_scheduleList.end())
|
|
return (*pos);
|
|
|
|
// throw an exception, if it does not exist
|
|
TQString msg = "Unknown schedule id '" + id + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
const TQValueList<MyMoneySchedule> MyMoneySeqAccessMgr::scheduleList(
|
|
const TQString& accountId,
|
|
const MyMoneySchedule::typeE type,
|
|
const MyMoneySchedule::occurenceE occurence,
|
|
const MyMoneySchedule::paymentTypeE paymentType,
|
|
const TQDate& startDate,
|
|
const TQDate& endDate,
|
|
const bool overdue) const
|
|
{
|
|
TQMap<TQString, MyMoneySchedule>::ConstIterator pos;
|
|
TQValueList<MyMoneySchedule> list;
|
|
|
|
// qDebug("scheduleList()");
|
|
|
|
for(pos = m_scheduleList.begin(); pos != m_scheduleList.end(); ++pos) {
|
|
// qDebug(" '%s'", qPrintable((*pos).id()));
|
|
|
|
if(type != MyMoneySchedule::TYPE_ANY) {
|
|
if(type != (*pos).type()) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if(occurence != MyMoneySchedule::OCCUR_ANY) {
|
|
if(occurence != (*pos).occurence()) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if(paymentType != MyMoneySchedule::STYPE_ANY) {
|
|
if(paymentType != (*pos).paymentType()) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if(!accountId.isEmpty()) {
|
|
MyMoneyTransaction t = (*pos).transaction();
|
|
TQValueList<MyMoneySplit>::ConstIterator it;
|
|
TQValueList<MyMoneySplit> splits;
|
|
splits = t.splits();
|
|
for(it = splits.begin(); it != splits.end(); ++it) {
|
|
if((*it).accountId() == accountId)
|
|
break;
|
|
}
|
|
if(it == splits.end()) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if(startDate.isValid() && endDate.isValid()) {
|
|
if((*pos).paymentDates(startDate, endDate).count() == 0) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if(startDate.isValid() && !endDate.isValid()) {
|
|
if(!(*pos).nextPayment(startDate.addDays(-1)).isValid()) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if(!startDate.isValid() && endDate.isValid()) {
|
|
if((*pos).startDate() > endDate) {
|
|
continue;
|
|
}
|
|
}
|
|
|
|
if(overdue) {
|
|
if (!(*pos).isOverdue())
|
|
continue;
|
|
}
|
|
|
|
// qDebug("Adding '%s'", (*pos).name().latin1());
|
|
list << *pos;
|
|
}
|
|
return list;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadSchedules(const TQMap<TQString, MyMoneySchedule>& map)
|
|
{
|
|
m_scheduleList = map;
|
|
|
|
// scan the map to identify the last used id
|
|
TQMap<TQString, MyMoneySchedule>::const_iterator it_s;
|
|
TQString lastId("");
|
|
for(it_s = map.begin(); it_s != map.end(); ++it_s) {
|
|
if((*it_s).id() > lastId)
|
|
lastId = (*it_s).id();
|
|
}
|
|
|
|
int pos = lastId.tqfind(TQRegExp("\\d+"), 0);
|
|
if(pos != -1) {
|
|
m_nextScheduleID = atol(lastId.mid(pos));
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadScheduleId(const unsigned long id)
|
|
{
|
|
m_nextScheduleID = id;
|
|
}
|
|
|
|
const TQValueList<MyMoneySchedule> MyMoneySeqAccessMgr::scheduleListEx(int scheduleTypes,
|
|
int scheduleOcurrences,
|
|
int schedulePaymentTypes,
|
|
TQDate date,
|
|
const TQStringList& accounts) const
|
|
{
|
|
// qDebug("scheduleListEx");
|
|
|
|
TQMap<TQString, MyMoneySchedule>::ConstIterator pos;
|
|
TQValueList<MyMoneySchedule> list;
|
|
|
|
if (!date.isValid())
|
|
return list;
|
|
|
|
for(pos = m_scheduleList.begin(); pos != m_scheduleList.end(); ++pos)
|
|
{
|
|
if (scheduleTypes && !(scheduleTypes & (*pos).type()))
|
|
continue;
|
|
|
|
if (scheduleOcurrences && !(scheduleOcurrences & (*pos).occurence()))
|
|
continue;
|
|
|
|
if (schedulePaymentTypes && !(schedulePaymentTypes & (*pos).paymentType()))
|
|
continue;
|
|
|
|
if((*pos).paymentDates(date, date).count() == 0)
|
|
continue;
|
|
|
|
if ((*pos).isFinished())
|
|
continue;
|
|
|
|
if ((*pos).hasRecordedPayment(date))
|
|
continue;
|
|
|
|
if (accounts.count() > 0)
|
|
{
|
|
if (accounts.tqcontains((*pos).account().id()))
|
|
continue;
|
|
}
|
|
|
|
// qDebug("\tAdding '%s'", (*pos).name().latin1());
|
|
list << *pos;
|
|
}
|
|
|
|
return list;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::addSecurity(MyMoneySecurity& security)
|
|
{
|
|
// create the account
|
|
MyMoneySecurity newSecurity(nextSecurityID(), security);
|
|
|
|
m_securitiesList.insert(newSecurity.id(), newSecurity);
|
|
|
|
security = newSecurity;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::modifySecurity(const MyMoneySecurity& security)
|
|
{
|
|
TQMap<TQString, MyMoneySecurity>::ConstIterator it;
|
|
|
|
it = m_securitiesList.tqfind(security.id());
|
|
if(it == m_securitiesList.end())
|
|
{
|
|
TQString msg = "Unknown security '";
|
|
msg += security.id() + "' during modifySecurity()";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
m_securitiesList.modify(security.id(), security);
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::removeSecurity(const MyMoneySecurity& security)
|
|
{
|
|
TQMap<TQString, MyMoneySecurity>::ConstIterator it;
|
|
|
|
// FIXME: check referential integrity
|
|
|
|
it = m_securitiesList.tqfind(security.id());
|
|
if(it == m_securitiesList.end())
|
|
{
|
|
TQString msg = "Unknown security '";
|
|
msg += security.id() + "' during removeSecurity()";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
m_securitiesList.remove(security.id());
|
|
}
|
|
|
|
const MyMoneySecurity MyMoneySeqAccessMgr::security(const TQString& id) const
|
|
{
|
|
TQMap<TQString, MyMoneySecurity>::ConstIterator it = m_securitiesList.tqfind(id);
|
|
if(it != m_securitiesList.end())
|
|
{
|
|
return it.data();
|
|
}
|
|
|
|
return MyMoneySecurity();
|
|
}
|
|
|
|
const TQValueList<MyMoneySecurity> MyMoneySeqAccessMgr::securityList(void) const
|
|
{
|
|
//qDebug("securityList: Security list size is %d, this=%8p", m_equitiesList.size(), (void*)this);
|
|
return m_securitiesList.values();
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::addCurrency(const MyMoneySecurity& currency)
|
|
{
|
|
TQMap<TQString, MyMoneySecurity>::ConstIterator it;
|
|
|
|
it = m_currencyList.tqfind(currency.id());
|
|
if(it != m_currencyList.end()) {
|
|
throw new MYMONEYEXCEPTION(TQString("Cannot add currency with existing id %1").tqarg(currency.id()));
|
|
}
|
|
|
|
m_currencyList.insert(currency.id(), currency);
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::modifyCurrency(const MyMoneySecurity& currency)
|
|
{
|
|
TQMap<TQString, MyMoneySecurity>::ConstIterator it;
|
|
|
|
it = m_currencyList.tqfind(currency.id());
|
|
if(it == m_currencyList.end()) {
|
|
throw new MYMONEYEXCEPTION(TQString("Cannot modify currency with unknown id %1").tqarg(currency.id()));
|
|
}
|
|
|
|
m_currencyList.modify(currency.id(), currency);
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::removeCurrency(const MyMoneySecurity& currency)
|
|
{
|
|
TQMap<TQString, MyMoneySecurity>::ConstIterator it;
|
|
|
|
// FIXME: check referential integrity
|
|
|
|
it = m_currencyList.tqfind(currency.id());
|
|
if(it == m_currencyList.end()) {
|
|
throw new MYMONEYEXCEPTION(TQString("Cannot remove currency with unknown id %1").tqarg(currency.id()));
|
|
}
|
|
|
|
m_currencyList.remove(currency.id());
|
|
}
|
|
|
|
const MyMoneySecurity MyMoneySeqAccessMgr::currency(const TQString& id) const
|
|
{
|
|
if(id.isEmpty()) {
|
|
|
|
}
|
|
TQMap<TQString, MyMoneySecurity>::ConstIterator it;
|
|
|
|
it = m_currencyList.tqfind(id);
|
|
if(it == m_currencyList.end()) {
|
|
throw new MYMONEYEXCEPTION(TQString("Cannot retrieve currency with unknown id '%1'").tqarg(id));
|
|
}
|
|
|
|
return *it;
|
|
}
|
|
|
|
const TQValueList<MyMoneySecurity> MyMoneySeqAccessMgr::currencyList(void) const
|
|
{
|
|
return m_currencyList.values();
|
|
}
|
|
|
|
const TQValueList<MyMoneyReport> MyMoneySeqAccessMgr::reportList(void) const
|
|
{
|
|
return m_reportList.values();
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::addReport( MyMoneyReport& report )
|
|
{
|
|
if(!report.id().isEmpty())
|
|
throw new MYMONEYEXCEPTION("report already contains an id");
|
|
|
|
MyMoneyReport newReport(nextReportID(), report);
|
|
m_reportList.insert(newReport.id(), newReport);
|
|
report = newReport;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadReports(const TQMap<TQString, MyMoneyReport>& map)
|
|
{
|
|
m_reportList = map;
|
|
|
|
// scan the map to identify the last used id
|
|
TQMap<TQString, MyMoneyReport>::const_iterator it_r;
|
|
TQString lastId("");
|
|
for(it_r = map.begin(); it_r != map.end(); ++it_r) {
|
|
if((*it_r).id() > lastId)
|
|
lastId = (*it_r).id();
|
|
}
|
|
|
|
int pos = lastId.tqfind(TQRegExp("\\d+"), 0);
|
|
if(pos != -1) {
|
|
m_nextReportID = atol(lastId.mid(pos));
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::modifyReport( const MyMoneyReport& report )
|
|
{
|
|
TQMap<TQString, MyMoneyReport>::ConstIterator it;
|
|
|
|
it = m_reportList.tqfind(report.id());
|
|
if(it == m_reportList.end()) {
|
|
TQString msg = "Unknown report '" + report.id() + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
m_reportList.modify(report.id(), report);
|
|
}
|
|
|
|
TQString MyMoneySeqAccessMgr::nextReportID(void)
|
|
{
|
|
TQString id;
|
|
id.setNum(++m_nextReportID);
|
|
id = "R" + id.rightJustify(REPORT_ID_SIZE, '0');
|
|
return id;
|
|
}
|
|
|
|
unsigned MyMoneySeqAccessMgr::countReports(void) const
|
|
{
|
|
return m_reportList.count();
|
|
}
|
|
|
|
const MyMoneyReport MyMoneySeqAccessMgr::report( const TQString& _id ) const
|
|
{
|
|
return m_reportList[_id];
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::removeReport( const MyMoneyReport& report )
|
|
{
|
|
TQMap<TQString, MyMoneyReport>::ConstIterator it;
|
|
|
|
it = m_reportList.tqfind(report.id());
|
|
if(it == m_reportList.end()) {
|
|
TQString msg = "Unknown report '" + report.id() + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
m_reportList.remove(report.id());
|
|
}
|
|
|
|
const TQValueList<MyMoneyBudget> MyMoneySeqAccessMgr::budgetList(void) const
|
|
{
|
|
return m_budgetList.values();
|
|
}
|
|
|
|
|
|
void MyMoneySeqAccessMgr::addBudget( MyMoneyBudget& budget )
|
|
{
|
|
MyMoneyBudget newBudget(nextBudgetID(), budget);
|
|
m_budgetList.insert(newBudget.id(), newBudget);
|
|
budget = newBudget;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::loadBudgets(const TQMap<TQString, MyMoneyBudget>& map)
|
|
{
|
|
m_budgetList = map;
|
|
|
|
// scan the map to identify the last used id
|
|
TQMap<TQString, MyMoneyBudget>::const_iterator it_b;
|
|
TQString lastId("");
|
|
for(it_b = map.begin(); it_b != map.end(); ++it_b) {
|
|
if((*it_b).id() > lastId)
|
|
lastId = (*it_b).id();
|
|
}
|
|
|
|
int pos = lastId.tqfind(TQRegExp("\\d+"), 0);
|
|
if(pos != -1) {
|
|
m_nextBudgetID = atol(lastId.mid(pos));
|
|
}
|
|
}
|
|
|
|
const MyMoneyBudget MyMoneySeqAccessMgr::budgetByName(const TQString& budget) const
|
|
{
|
|
TQMap<TQString, MyMoneyBudget>::ConstIterator it_p;
|
|
|
|
for(it_p = m_budgetList.begin(); it_p != m_budgetList.end(); ++it_p) {
|
|
if((*it_p).name() == budget) {
|
|
return *it_p;
|
|
}
|
|
}
|
|
|
|
throw new MYMONEYEXCEPTION("Unknown budget '" + budget + "'");
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::modifyBudget( const MyMoneyBudget& budget )
|
|
{
|
|
TQMap<TQString, MyMoneyBudget>::ConstIterator it;
|
|
|
|
it = m_budgetList.tqfind(budget.id());
|
|
if(it == m_budgetList.end()) {
|
|
TQString msg = "Unknown budget '" + budget.id() + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
m_budgetList.modify(budget.id(), budget);
|
|
}
|
|
|
|
TQString MyMoneySeqAccessMgr::nextBudgetID(void)
|
|
{
|
|
TQString id;
|
|
id.setNum(++m_nextBudgetID);
|
|
id = "B" + id.rightJustify(BUDGET_ID_SIZE, '0');
|
|
return id;
|
|
}
|
|
|
|
unsigned MyMoneySeqAccessMgr::countBudgets(void) const
|
|
{
|
|
return m_budgetList.count();
|
|
}
|
|
|
|
MyMoneyBudget MyMoneySeqAccessMgr::budget( const TQString& _id ) const
|
|
{
|
|
return m_budgetList[_id];
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::removeBudget( const MyMoneyBudget& budget )
|
|
{
|
|
TQMap<TQString, MyMoneyBudget>::ConstIterator it;
|
|
|
|
it = m_budgetList.tqfind(budget.id());
|
|
if(it == m_budgetList.end()) {
|
|
TQString msg = "Unknown budget '" + budget.id() + "'";
|
|
throw new MYMONEYEXCEPTION(msg);
|
|
}
|
|
|
|
m_budgetList.remove(budget.id());
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::addPrice(const MyMoneyPrice& price)
|
|
{
|
|
MyMoneySecurityPair pricePair(price.from(), price.to());
|
|
TQMap<MyMoneySecurityPair, MyMoneyPriceEntries>::ConstIterator it_m;
|
|
it_m = m_priceList.tqfind(pricePair);
|
|
|
|
MyMoneyPriceEntries entries;
|
|
if(it_m != m_priceList.end()) {
|
|
entries = (*it_m);
|
|
}
|
|
// entries contains the current entries for this security pair
|
|
// in case it_m points to m_priceList.end() we need to create a
|
|
// new entry in the priceList, otherwise we need to modify
|
|
// an existing one.
|
|
|
|
MyMoneyPriceEntries::ConstIterator it;
|
|
it = entries.tqfind(price.date());
|
|
if(it != entries.end()) {
|
|
if((*it).rate(TQString()) == price.rate(TQString())
|
|
&& (*it).source() == price.source())
|
|
// in case the information did not change, we don't do anything
|
|
return;
|
|
}
|
|
|
|
// store new value in local copy
|
|
entries[price.date()] = price;
|
|
|
|
if(it_m != m_priceList.end()) {
|
|
m_priceList.modify(pricePair, entries);
|
|
} else {
|
|
m_priceList.insert(pricePair, entries);
|
|
}
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::removePrice(const MyMoneyPrice& price)
|
|
{
|
|
MyMoneySecurityPair pricePair(price.from(), price.to());
|
|
TQMap<MyMoneySecurityPair, MyMoneyPriceEntries>::ConstIterator it_m;
|
|
it_m = m_priceList.tqfind(pricePair);
|
|
|
|
MyMoneyPriceEntries entries;
|
|
if(it_m != m_priceList.end()) {
|
|
entries = (*it_m);
|
|
}
|
|
|
|
// store new value in local copy
|
|
entries.remove(price.date());
|
|
|
|
if(entries.count() != 0) {
|
|
m_priceList.modify(pricePair, entries);
|
|
} else {
|
|
m_priceList.remove(pricePair);
|
|
}
|
|
}
|
|
|
|
const MyMoneyPriceList MyMoneySeqAccessMgr::priceList(void) const
|
|
{
|
|
MyMoneyPriceList list;
|
|
m_priceList.map(list);
|
|
return list;
|
|
}
|
|
|
|
const MyMoneyPrice MyMoneySeqAccessMgr::price(const TQString& fromId, const TQString& toId, const TQDate& _date, const bool exactDate) const
|
|
{
|
|
MyMoneyPrice rc;
|
|
MyMoneyPriceEntries::ConstIterator it;
|
|
TQDate date(_date);
|
|
|
|
// If no valid date is passed, we use today's date.
|
|
if(!date.isValid())
|
|
date = TQDate::tqcurrentDate();
|
|
|
|
// If the caller selected an exact entry, we can search for
|
|
// it using the date as the key
|
|
if(exactDate) {
|
|
it = m_priceList[MyMoneySecurityPair(fromId, toId)].tqfind(date);
|
|
if(it != m_priceList[MyMoneySecurityPair(fromId, toId)].end())
|
|
rc = *it;
|
|
|
|
} else {
|
|
// otherwise, we must scan the map for the previous price entry
|
|
for(it = m_priceList[MyMoneySecurityPair(fromId, toId)].begin(); it != m_priceList[MyMoneySecurityPair(fromId, toId)].end(); ++it) {
|
|
if(date < it.key())
|
|
break;
|
|
|
|
if(date >= it.key())
|
|
rc = *it;
|
|
}
|
|
}
|
|
return rc;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::clearCache(void)
|
|
{
|
|
m_balanceCache.clear();
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::rebuildAccountBalances(void)
|
|
{
|
|
// reset the balance of all accounts to 0
|
|
TQMap<TQString, MyMoneyAccount> map;
|
|
m_accountList.map(map);
|
|
|
|
TQMap<TQString, MyMoneyAccount>::iterator it_a;
|
|
for(it_a = map.begin(); it_a != map.end(); ++it_a) {
|
|
(*it_a).setBalance(MyMoneyMoney(0));
|
|
}
|
|
|
|
// now scan over all transactions and all splits and setup the balances
|
|
TQMap<TQString, MyMoneyTransaction>::const_iterator it_t;
|
|
for(it_t = m_transactionList.begin(); it_t != m_transactionList.end(); ++it_t) {
|
|
const TQValueList<MyMoneySplit>& splits = (*it_t).splits();
|
|
TQValueList<MyMoneySplit>::const_iterator it_s = splits.begin();
|
|
for(; it_s != splits.end(); ++it_s ) {
|
|
if(!(*it_s).shares().isZero()) {
|
|
const TQString& id = (*it_s).accountId();
|
|
// locate the account and if present, update data
|
|
if(map.tqfind(id) != map.end()) {
|
|
map[id].adjustBalance(*it_s);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
m_accountList = map;
|
|
}
|
|
|
|
bool MyMoneySeqAccessMgr::isReferenced(const MyMoneyObject& obj, const MyMoneyFileBitArray& skipCheck) const
|
|
{
|
|
// We delete all references in reports when an object
|
|
// is deleted, so we don't need to check here. See
|
|
// MyMoneySeqAccessMgr::removeReferences(). In case
|
|
// you miss the report checks in the following lines ;)
|
|
|
|
bool rc = false;
|
|
const TQString& id = obj.id();
|
|
TQMap<TQString, MyMoneyTransaction>::const_iterator it_t;
|
|
TQMap<TQString, MyMoneyAccount>::const_iterator it_a;
|
|
TQMap<TQString, MyMoneyInstitution>::const_iterator it_i;
|
|
TQMap<TQString, MyMoneyPayee>::const_iterator it_p;
|
|
TQMap<TQString, MyMoneyBudget>::const_iterator it_b;
|
|
TQMap<TQString, MyMoneySchedule>::const_iterator it_sch;
|
|
TQMap<TQString, MyMoneySecurity>::const_iterator it_sec;
|
|
MyMoneyPriceList::const_iterator it_pr;
|
|
|
|
// FIXME optimize the list of objects we have to checks
|
|
// with a bit of knowledge of the internal structure, we
|
|
// could optimize the number of objects we check for references
|
|
|
|
// Scan all engine objects for a reference
|
|
if(!skipCheck[RefCheckTransaction]) {
|
|
for(it_t = m_transactionList.begin(); !rc && it_t != m_transactionList.end(); ++it_t) {
|
|
rc = (*it_t).hasReferenceTo(id);
|
|
}
|
|
}
|
|
|
|
if(!skipCheck[RefCheckAccount]) {
|
|
for(it_a = m_accountList.begin(); !rc && it_a != m_accountList.end(); ++it_a) {
|
|
rc = (*it_a).hasReferenceTo(id);
|
|
}
|
|
}
|
|
if(!skipCheck[RefCheckInstitution]) {
|
|
for(it_i = m_institutionList.begin(); !rc && it_i != m_institutionList.end(); ++it_i) {
|
|
rc = (*it_i).hasReferenceTo(id);
|
|
}
|
|
}
|
|
if(!skipCheck[RefCheckPayee]) {
|
|
for(it_p = m_payeeList.begin(); !rc && it_p != m_payeeList.end(); ++it_p) {
|
|
rc = (*it_p).hasReferenceTo(id);
|
|
}
|
|
}
|
|
|
|
if(!skipCheck[RefCheckBudget]) {
|
|
for(it_b = m_budgetList.begin(); !rc && it_b != m_budgetList.end(); ++it_b) {
|
|
rc = (*it_b).hasReferenceTo(id);
|
|
}
|
|
}
|
|
if(!skipCheck[RefCheckSchedule]) {
|
|
for(it_sch = m_scheduleList.begin(); !rc && it_sch != m_scheduleList.end(); ++it_sch) {
|
|
rc = (*it_sch).hasReferenceTo(id);
|
|
}
|
|
}
|
|
if(!skipCheck[RefCheckSecurity]) {
|
|
for(it_sec = m_securitiesList.begin(); !rc && it_sec != m_securitiesList.end(); ++it_sec) {
|
|
rc = (*it_sec).hasReferenceTo(id);
|
|
}
|
|
}
|
|
if(!skipCheck[RefCheckCurrency]) {
|
|
for(it_sec = m_currencyList.begin(); !rc && it_sec != m_currencyList.end(); ++it_sec) {
|
|
rc = (*it_sec).hasReferenceTo(id);
|
|
}
|
|
}
|
|
// within the pricelist we don't have to scan each entry. Checking the TQPair
|
|
// members of the MyMoneySecurityPair is enough as they are identical to the
|
|
// two security ids
|
|
if(!skipCheck[RefCheckPrice]) {
|
|
for(it_pr = m_priceList.begin(); !rc && it_pr != m_priceList.end(); ++it_pr) {
|
|
rc = (it_pr.key().first == id) || (it_pr.key().second == id);
|
|
}
|
|
}
|
|
|
|
return rc;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::startTransaction(void)
|
|
{
|
|
m_payeeList.startTransaction(&m_nextPayeeID);
|
|
m_institutionList.startTransaction(&m_nextInstitutionID);
|
|
m_accountList.startTransaction(&m_nextPayeeID);
|
|
m_transactionList.startTransaction(&m_nextTransactionID);
|
|
m_transactionKeys.startTransaction();
|
|
m_scheduleList.startTransaction(&m_nextScheduleID);
|
|
m_securitiesList.startTransaction(&m_nextSecurityID);
|
|
m_currencyList.startTransaction();
|
|
m_reportList.startTransaction(&m_nextReportID);
|
|
m_budgetList.startTransaction(&m_nextBudgetID);
|
|
m_priceList.startTransaction();
|
|
}
|
|
|
|
bool MyMoneySeqAccessMgr::commitTransaction(void)
|
|
{
|
|
bool rc = false;
|
|
rc |= m_payeeList.commitTransaction();
|
|
rc |= m_institutionList.commitTransaction();
|
|
rc |= m_accountList.commitTransaction();
|
|
rc |= m_transactionList.commitTransaction();
|
|
rc |= m_transactionKeys.commitTransaction();
|
|
rc |= m_scheduleList.commitTransaction();
|
|
rc |= m_securitiesList.commitTransaction();
|
|
rc |= m_currencyList.commitTransaction();
|
|
rc |= m_reportList.commitTransaction();
|
|
rc |= m_budgetList.commitTransaction();
|
|
rc |= m_priceList.commitTransaction();
|
|
|
|
// if there was a change, touch the whole storage object
|
|
if(rc)
|
|
touch();
|
|
|
|
return rc;
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::rollbackTransaction(void)
|
|
{
|
|
m_payeeList.rollbackTransaction();
|
|
m_institutionList.rollbackTransaction();
|
|
m_accountList.rollbackTransaction();
|
|
m_transactionList.rollbackTransaction();
|
|
m_transactionKeys.rollbackTransaction();
|
|
m_scheduleList.rollbackTransaction();
|
|
m_securitiesList.rollbackTransaction();
|
|
m_currencyList.rollbackTransaction();
|
|
m_reportList.rollbackTransaction();
|
|
m_budgetList.rollbackTransaction();
|
|
m_priceList.rollbackTransaction();
|
|
}
|
|
|
|
void MyMoneySeqAccessMgr::removeReferences(const TQString& id)
|
|
{
|
|
TQMap<TQString, MyMoneyReport>::const_iterator it_r;
|
|
TQMap<TQString, MyMoneyBudget>::const_iterator it_b;
|
|
|
|
// remove from reports
|
|
for(it_r = m_reportList.begin(); it_r != m_reportList.end(); ++it_r) {
|
|
MyMoneyReport r = *it_r;
|
|
r.removeReference(id);
|
|
m_reportList.modify(r.id(), r);
|
|
}
|
|
|
|
// remove from budgets
|
|
for(it_b = m_budgetList.begin(); it_b != m_budgetList.end(); ++it_b) {
|
|
MyMoneyBudget b = *it_b;
|
|
b.removeReference(id);
|
|
m_budgetList.modify(b.id(), b);
|
|
}
|
|
}
|
|
|
|
#undef TRY
|
|
#undef CATCH
|
|
#undef PASS
|
|
|
|
// vim:cin:si:ai:et:ts=2:sw=2:
|