void KNewAccountDlg::showSubAccounts(QStringList accounts, KMyMoneyAccountTreeBaseItem *parentItem, const QString& parentId, const QString& accountId) { MyMoneyFile *file = MyMoneyFile::instance(); for ( QStringList::ConstIterator it = accounts.begin(); it != accounts.end(); ++it ) { KMyMoneyAccountTreeBaseItem *accountItem = new KMyMoneyAccountTreeItem(parentItem, file->account(*it)); QString id = file->account(*it).id(); if(parentId == id) { m_parentItem = accountItem; } else if(accountId == id) { if(m_isEditing) accountItem->setSelectable(false); m_accountItem = accountItem; } QStringList subAccounts = file->account(*it).accountList(); if (subAccounts.count() >= 1) { showSubAccounts(subAccounts, accountItem, parentId, accountId); } } }
void ReportAccount::calculateAccountHierarchy() { DEBUG_ENTER(Q_FUNC_INFO); MyMoneyFile* file = MyMoneyFile::instance(); QString resultid = id(); QString parentid = parentAccountId(); #ifdef DEBUG_HIDE_SENSITIVE m_nameHierarchy.prepend(file->account(resultid).id()); #else m_nameHierarchy.prepend(file->account(resultid).name()); #endif while (!parentid.isEmpty() && !file->isStandardAccount(parentid)) { // take on the identity of our parent resultid = parentid; // and try again parentid = file->account(resultid).parentAccountId(); #ifdef DEBUG_HIDE_SENSITIVE m_nameHierarchy.prepend(file->account(resultid).id()); #else m_nameHierarchy.prepend(file->account(resultid).name()); #endif } }
void KForecastView::loadAccounts(MyMoneyForecast& forecast, const MyMoneyAccount& account, QTreeWidgetItem* parentItem, int forecastType) { QMap<QString, QString> nameIdx; QStringList accList; MyMoneyFile* file = MyMoneyFile::instance(); QTreeWidgetItem *forecastItem = 0; //Get all accounts of the right type to calculate forecast accList = account.accountList(); if (accList.size() == 0) return; QStringList::ConstIterator accList_t; for (accList_t = accList.constBegin(); accList_t != accList.constEnd(); ++accList_t) { MyMoneyAccount subAccount = file->account(*accList_t); //only add the account if it is a forecast account or the parent of a forecast account if (includeAccount(forecast, subAccount)) { nameIdx[subAccount.id()] = subAccount.id(); } } QMap<QString, QString>::ConstIterator it_nc; for (it_nc = nameIdx.constBegin(); it_nc != nameIdx.constEnd(); ++it_nc) { const MyMoneyAccount subAccount = file->account(*it_nc); MyMoneySecurity currency; if (subAccount.isInvest()) { MyMoneySecurity underSecurity = file->security(subAccount.currencyId()); currency = file->security(underSecurity.tradingCurrency()); } else { currency = file->security(subAccount.currencyId()); } forecastItem = new QTreeWidgetItem(parentItem); forecastItem->setText(0, subAccount.name()); forecastItem->setIcon(0, subAccount.accountPixmap()); forecastItem->setData(0, ForecastRole, QVariant::fromValue(forecast)); forecastItem->setData(0, AccountRole, QVariant::fromValue(subAccount)); forecastItem->setExpanded(true); switch (forecastType) { case eSummary: updateSummary(forecastItem); break; case eDetailed: updateDetailed(forecastItem); break; case eBudget: updateBudget(forecastItem); break; default: break; } loadAccounts(forecast, subAccount, forecastItem, forecastType); } }
void MyMoneyForecast::addFutureTransactions(void) { MyMoneyTransactionFilter filter; MyMoneyFile* file = MyMoneyFile::instance(); // collect and process all transactions that have already been entered but // are located in the future. filter.setDateFilter(forecastStartDate(), forecastEndDate()); filter.setReportAllSplits(false); QValueList<MyMoneyTransaction> transactions = file->transactionList(filter); QValueList<MyMoneyTransaction>::const_iterator it_t = transactions.begin(); for(; it_t != transactions.end(); ++it_t ) { const QValueList<MyMoneySplit>& splits = (*it_t).splits(); QValueList<MyMoneySplit>::const_iterator it_s = splits.begin(); for(; it_s != splits.end(); ++it_s ) { if(!(*it_s).shares().isZero()) { MyMoneyAccount acc = file->account((*it_s).accountId()); if(isForecastAccount(acc)) { dailyBalances balance; balance = m_accountList[acc.id()]; //if it is income, the balance is stored as negative number if(acc.accountType() == MyMoneyAccount::Income) { balance[(*it_t).postDate()] += ((*it_s).shares() * MyMoneyMoney(-1, 1)); } else { balance[(*it_t).postDate()] += (*it_s).shares(); } m_accountList[acc.id()] = balance; } } } } #if 0 QFile trcFile("forecast.csv"); trcFile.open(IO_WriteOnly); QTextStream s(&trcFile); { s << "Already present transactions\n"; QMap<QString, dailyBalances>::Iterator it_a; QMap<QString, QString>::ConstIterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); it_a = m_accountList.find(*it_n); s << "\"" << acc.name() << "\","; for(int i = 0; i < 90; ++i) { s << "\"" << (*it_a)[i].formatMoney("") << "\","; } s << "\n"; } } #endif }
void KImportDlg::addCategories(QStringList& strList, const QString& id, const QString& leadIn) const { MyMoneyFile *file = MyMoneyFile::instance(); QString name; MyMoneyAccount account = file->account(id); QStringList accList = account.accountList(); QStringList::ConstIterator it_a; for (it_a = accList.constBegin(); it_a != accList.constEnd(); ++it_a) { account = file->account(*it_a); strList << leadIn + account.name(); addCategories(strList, *it_a, leadIn + account.name() + MyMoneyFile::AccountSeperator); } }
void CsvUtil::previouslyUsedCategories(const QString& investmentAccount, QString& feesId, QString& interestId) { feesId.clear(); interestId.clear(); 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()); QList< QPair<MyMoneyTransaction, MyMoneySplit> > list; file->transactionList(list, filter); QList< QPair<MyMoneyTransaction, MyMoneySplit> >::const_iterator it_t; for (it_t = list.constBegin(); it_t != list.constEnd(); ++it_t) { const MyMoneyTransaction& t = (*it_t).first; const MyMoneySplit&s = (*it_t).second; MyMoneySplit assetAccountSplit; QList<MyMoneySplit> feeSplits; QList<MyMoneySplit> interestSplits; MyMoneySecurity security; MyMoneySecurity currency; MyMoneySplit::investTransactionTypeE transactionType; 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 (const MyMoneyException &) { } }
void MyMoneyQifWriter::writeTransactionEntry(QTextStream &s, const MyMoneyTransaction& t, const QString& accountId) { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneySplit split = t.splitByAccount(accountId); s << "D" << m_qifProfile.date(t.postDate()) << endl; switch(split.reconcileFlag()) { case MyMoneySplit::Cleared: s << "C*" << endl; break; case MyMoneySplit::Reconciled: case MyMoneySplit::Frozen: s << "CX" << endl; break; default: break; } if(split.memo().length() > 0) { QString m = split.memo(); m.replace('\n', "\\n"); s << "M" << m << endl; } s << "T" << m_qifProfile.value('T', split.value()) << endl; if(split.number().length() > 0) s << "N" << split.number() << endl; if(!split.payeeId().isEmpty()) { MyMoneyPayee payee = file->payee(split.payeeId()); s << "P" << payee.name() << endl; } QValueList<MyMoneySplit> list = t.splits(); if(list.count() > 1) { MyMoneySplit sp = t.splitByAccount(accountId, false); MyMoneyAccount acc = file->account(sp.accountId()); if(acc.accountGroup() != MyMoneyAccount::Income && acc.accountGroup() != MyMoneyAccount::Expense) { s << "L" << m_qifProfile.accountDelimiter()[0] << MyMoneyFile::instance()->accountToCategory(sp.accountId()) << m_qifProfile.accountDelimiter()[1] << endl; } else { s << "L" << file->accountToCategory(sp.accountId()) << endl; } if(list.count() > 2) { QValueList<MyMoneySplit>::ConstIterator it; for(it = list.begin(); it != list.end(); ++it) { if(!((*it) == split)) { writeSplitEntry(s, *it); } } } } s << "^" << endl; }
TransactionHelper::TransactionHelper( const QDate& _date, const QString& _action, MyMoneyMoney _value, const QString& _accountid, const QString& _categoryid, const QString& _currencyid, const QString& _payee ) { // _currencyid is the currency of the transaction, and of the _value // both the account and category can have their own currency (athough the category having // a foreign currency is not yet supported by the program, the reports will still allow it, // so it must be tested.) MyMoneyFile* file = MyMoneyFile::instance(); bool haspayee = ! _payee.isEmpty(); MyMoneyPayee payeeTest = file->payeeByName(_payee); MyMoneyFileTransaction ft; setPostDate(_date); QString currencyid = _currencyid; if ( currencyid.isEmpty() ) currencyid=MyMoneyFile::instance()->baseCurrency().id(); setCommodity(currencyid); MyMoneyMoney price; MyMoneySplit splitLeft; if ( haspayee ) splitLeft.setPayeeId(payeeTest.id()); splitLeft.setAction(_action); splitLeft.setValue(-_value); price = MyMoneyFile::instance()->price(currencyid, file->account(_accountid).currencyId(),_date).rate(file->account(_accountid).currencyId()); splitLeft.setShares(-_value * price); splitLeft.setAccountId(_accountid); addSplit(splitLeft); MyMoneySplit splitRight; if ( haspayee ) splitRight.setPayeeId(payeeTest.id()); splitRight.setAction(_action); splitRight.setValue(_value); price = MyMoneyFile::instance()->price(currencyid, file->account(_categoryid).currencyId(),_date).rate(file->account(_categoryid).currencyId()); splitRight.setShares(_value * price ); splitRight.setAccountId(_categoryid); addSplit(splitRight); MyMoneyFile::instance()->addTransaction(*this); ft.commit(); }
void MyMoneyForecast::calculateHistoricDailyBalances() { MyMoneyFile* file = MyMoneyFile::instance(); calculateAccountTrendList(); //Calculate account daily balances QMap<QString, QString>::ConstIterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); //set the starting balance of the account setStartingBalance(acc); switch(historyMethod()) { case 0: case 1: { for(QDate f_day = forecastStartDate(); f_day <= forecastEndDate(); ) { for(int t_day = 1; t_day <= accountsCycle(); ++t_day) { MyMoneyMoney balanceDayBefore = m_accountList[acc.id()][(f_day.addDays(-1))];//balance of the day before MyMoneyMoney accountDailyTrend = m_accountTrendList[acc.id()][t_day]; //trend for that day //balance of the day is the balance of the day before multiplied by the trend for the day m_accountList[acc.id()][f_day] = balanceDayBefore; m_accountList[acc.id()][f_day] += accountDailyTrend; //movement trend for that particular day m_accountList[acc.id()][f_day] = m_accountList[acc.id()][f_day].convert(acc.fraction()); //m_accountList[acc.id()][f_day] += m_accountListPast[acc.id()][f_day.addDays(-historyDays())]; f_day = f_day.addDays(1); } } } break; case 2: { QDate baseDate = QDate::currentDate().addDays(-accountsCycle()); for(int t_day = 1; t_day <= accountsCycle(); ++t_day) { int f_day = 1; QDate fDate = baseDate.addDays(accountsCycle()+1); while (fDate <= forecastEndDate()) { //the calculation is based on the balance for the last month, that is then multiplied by the trend m_accountList[acc.id()][fDate] = m_accountListPast[acc.id()][baseDate] + (m_accountTrendList[acc.id()][t_day] * MyMoneyMoney(f_day,1)); m_accountList[acc.id()][fDate] = m_accountList[acc.id()][fDate].convert(acc.fraction()); ++f_day; fDate = baseDate.addDays(accountsCycle() * f_day); } baseDate = baseDate.addDays(1); } } } } }
void MyMoneyQifWriter::writeAccountEntry(QTextStream &s, const QString& accountId, const QDate& startDate, const QDate& endDate) { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyAccount account; account = file->account(accountId); MyMoneyTransactionFilter filter(accountId); filter.setDateFilter(startDate, endDate); QValueList<MyMoneyTransaction> list = file->transactionList(filter); QString openingBalanceTransactionId; s << "!Type:" << m_qifProfile.profileType() << endl; if(!startDate.isValid() || startDate <= account.openingDate()) { s << "D" << m_qifProfile.date(account.openingDate()) << endl; openingBalanceTransactionId = file->openingBalanceTransaction(account); MyMoneySplit split; if(!openingBalanceTransactionId.isEmpty()) { MyMoneyTransaction openingBalanceTransaction = file->transaction(openingBalanceTransactionId); split = openingBalanceTransaction.splitByAccount(account.id(), true /* match */); } s << "T" << m_qifProfile.value('T', split.value()) << endl; } else { s << "D" << m_qifProfile.date(startDate) << endl; s << "T" << m_qifProfile.value('T', file->balance(accountId, startDate.addDays(-1))) << endl; } s << "CX" << endl; s << "P" << m_qifProfile.openingBalanceText() << endl; s << "L"; if(m_qifProfile.accountDelimiter().length()) s << m_qifProfile.accountDelimiter()[0]; s << account.name(); if(m_qifProfile.accountDelimiter().length() > 1) s << m_qifProfile.accountDelimiter()[1]; s << endl; s << "^" << endl; QValueList<MyMoneyTransaction>::ConstIterator it; signalProgress(0, list.count()); int count = 0; for(it = list.begin(); it != list.end(); ++it) { // don't include the openingBalanceTransaction again if((*it).id() != openingBalanceTransactionId) writeTransactionEntry(s, *it, accountId); signalProgress(++count, 0); } }
void MyMoneyForecast::doFutureScheduledForecast(void) { MyMoneyFile* file = MyMoneyFile::instance(); if(isIncludingFutureTransactions()) addFutureTransactions(); if(isIncludingScheduledTransactions()) addScheduledTransactions(); //do not show accounts with no transactions if(!isIncludingUnusedAccounts()) purgeForecastAccountsList(m_accountList); //adjust value of investments to deep currency QMap<QString, QString>::ConstIterator it_n; for ( it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n ) { MyMoneyAccount acc = file->account ( *it_n ); if ( acc.isInvest() ) { //get the id of the security for that account MyMoneySecurity undersecurity = file->security ( acc.currencyId() ); //only do it if the security is not an actual currency if ( ! undersecurity.isCurrency() ) { //set the default value MyMoneyMoney rate = MyMoneyMoney ( 1, 1 ); MyMoneyPrice price; for (QDate it_day = QDate::currentDate(); it_day <= forecastEndDate(); ) { //get the price for the tradingCurrency that day price = file->price ( undersecurity.id(), undersecurity.tradingCurrency(), it_day ); if ( price.isValid() ) { rate = price.rate ( undersecurity.tradingCurrency() ); } //value is the amount of shares multiplied by the rate of the deep currency m_accountList[acc.id() ][it_day] = m_accountList[acc.id() ][it_day] * rate; it_day = it_day.addDays(1); } } } } }
void CsvUtil::dissectTransaction(const MyMoneyTransaction& transaction, const MyMoneySplit& split, MyMoneySplit& assetAccountSplit, QList<MyMoneySplit>& feeSplits, QList<MyMoneySplit>& interestSplits, MyMoneySecurity& security, MyMoneySecurity& currency, MyMoneySplit::investTransactionTypeE& transactionType) { // collect the splits. split references the stock account and should already // be set up. assetAccountSplit references the corresponding asset account (maybe // empty), feeSplits is the list of all expenses and interestSplits // the list of all incomes MyMoneyFile* file = MyMoneyFile::instance(); QList<MyMoneySplit>::ConstIterator it_s; for (it_s = transaction.splits().constBegin(); it_s != transaction.splits().constEnd(); ++it_s) { MyMoneyAccount acc = file->account((*it_s).accountId()); if ((*it_s).id() == split.id()) { security = file->security(acc.currencyId()); } else if (acc.accountGroup() == MyMoneyAccount::Expense) { feeSplits.append(*it_s); } else if (acc.accountGroup() == MyMoneyAccount::Income) { interestSplits.append(*it_s); } else { assetAccountSplit = *it_s; } } // determine transaction type if (split.action() == MyMoneySplit::ActionAddShares) { transactionType = (!split.shares().isNegative()) ? MyMoneySplit::AddShares : MyMoneySplit::RemoveShares; } else if (split.action() == MyMoneySplit::ActionBuyShares) { transactionType = (!split.value().isNegative()) ? MyMoneySplit::BuyShares : MyMoneySplit::SellShares; } else if (split.action() == MyMoneySplit::ActionDividend) { transactionType = MyMoneySplit::Dividend; } else if (split.action() == MyMoneySplit::ActionReinvestDividend) { transactionType = MyMoneySplit::ReinvestDividend; } else if (split.action() == MyMoneySplit::ActionYield) { transactionType = MyMoneySplit::Yield; } else if (split.action() == MyMoneySplit::ActionSplitShares) { transactionType = MyMoneySplit::SplitShares; } else if (split.action() == MyMoneySplit::ActionInterestIncome) { transactionType = MyMoneySplit::InterestIncome; } else transactionType = MyMoneySplit::BuyShares; currency.setTradingSymbol("???"); try { currency = file->security(transaction.commodity()); } catch (const MyMoneyException &) { } }
ReportAccount ReportAccount::topParent() const { DEBUG_ENTER(Q_FUNC_INFO); MyMoneyFile* file = MyMoneyFile::instance(); QString resultid = id(); QString parentid = parentAccountId(); while (!parentid.isEmpty() && !file->isStandardAccount(parentid)) { // take on the identity of our parent resultid = parentid; // and try again parentid = file->account(resultid).parentAccountId(); } return ReportAccount(resultid); }
bool KForecastView::includeAccount(MyMoneyForecast& forecast, const MyMoneyAccount& acc) { MyMoneyFile* file = MyMoneyFile::instance(); if (forecast.isForecastAccount(acc)) return true; QStringList accounts = acc.accountList(); if (accounts.size() > 0) { QStringList::ConstIterator it_acc; for (it_acc = accounts.constBegin(); it_acc != accounts.constEnd(); ++it_acc) { MyMoneyAccount account = file->account(*it_acc); if (includeAccount(forecast, account)) return true; } } return false; }
void KNewAccountDlg::slotSelectionChanged(QListViewItem *item) { KMyMoneyAccountTreeBaseItem *accountItem = dynamic_cast<KMyMoneyAccountTreeBaseItem*>(item); try { MyMoneyFile *file = MyMoneyFile::instance(); //qDebug("Selected account id: %s", accountItem->accountID().data()); m_parentAccount = file->account(accountItem->id()); m_subAccountLabel->setText(i18n("Is a sub account of %1").arg(m_parentAccount.name())); if(m_qlistviewParentAccounts->isEnabled()) { m_bSelectedParentAccount = true; } } catch (MyMoneyException *e) { qDebug("This shouldn't happen! : %s", e->what().latin1()); delete e; } }
void MyMoneyForecast::calculateScheduledMonthlyBalances() { MyMoneyFile* file = MyMoneyFile::instance(); //Calculate account monthly balances QMap<QString, QString>::ConstIterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); for( QDate f_date = forecastStartDate(); f_date <= forecastEndDate(); f_date = f_date.addDays(1) ) { //get the trend for the day MyMoneyMoney accountDailyBalance = m_accountList[acc.id()][f_date]; //do not add if it is the beginning of the month //otherwise we end up with duplicated values as reported by Marko Käning if(f_date != QDate(f_date.year(), f_date.month(), 1) ) m_accountList[acc.id()][QDate(f_date.year(), f_date.month(), 1)] += accountDailyBalance; } } }
void MyMoneyForecast::calculateHistoricMonthlyBalances() { MyMoneyFile* file = MyMoneyFile::instance(); //Calculate account monthly balances QMap<QString, QString>::ConstIterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); for( QDate f_date = forecastStartDate(); f_date <= forecastEndDate(); ) { for(int f_day = 1; f_day <= accountsCycle() && f_date <= forecastEndDate(); ++f_day) { MyMoneyMoney accountDailyTrend = m_accountTrendList[acc.id()][f_day]; //trend for that day //check for leap year if(f_date.month() == 2 && f_date.day() == 29) f_date = f_date.addDays(1); //skip 1 day m_accountList[acc.id()][QDate(f_date.year(), f_date.month(), 1)] += accountDailyTrend; //movement trend for that particular day f_date = f_date.addDays(1); } } } }
void MyMoneyForecast::calculateScheduledDailyBalances (void) { MyMoneyFile* file = MyMoneyFile::instance(); //Calculate account daily balances QMap<QString, QString>::ConstIterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); //set the starting balance of the account setStartingBalance(acc); for(QDate f_day = forecastStartDate(); f_day <= forecastEndDate(); ) { MyMoneyMoney balanceDayBefore = m_accountList[acc.id()][(f_day.addDays(-1))];//balance of the day before m_accountList[acc.id()][f_day] += balanceDayBefore; //running sum f_day = f_day.addDays(1); } } }
void MyMoneyQifWriter::writeSplitEntry(QTextStream& s, const MyMoneySplit& split) { MyMoneyFile* file = MyMoneyFile::instance(); s << "S"; MyMoneyAccount acc = file->account(split.accountId()); if(acc.accountGroup() != MyMoneyAccount::Income && acc.accountGroup() != MyMoneyAccount::Expense) { s << m_qifProfile.accountDelimiter()[0] << file->accountToCategory(split.accountId()) << m_qifProfile.accountDelimiter()[1]; } else { s << file->accountToCategory(split.accountId()); } s << endl; if(split.memo().length() > 0) { QString m = split.memo(); m.replace('\n', "\\n"); s << "E" << m << endl; } s << "$" << m_qifProfile.value('$', -split.value()) << endl; }
void InvTransactionHelper::init( const QDate& _date, const QString& _action, MyMoneyMoney _shares, MyMoneyMoney _price, const QString& _stockaccountid, const QString& _transferid, const QString& _categoryid ) { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyAccount stockaccount = file->account(_stockaccountid); MyMoneyMoney value = _shares * _price; setPostDate(_date); setCommodity("USD"); MyMoneySplit s1; s1.setValue(value); s1.setAccountId(_stockaccountid); if ( _action == MyMoneySplit::ActionReinvestDividend ) { s1.setShares(_shares); s1.setAction(MyMoneySplit::ActionReinvestDividend); MyMoneySplit s2; s2.setAccountId(_categoryid); s2.setShares(-value); s2.setValue(-value); addSplit(s2); } else if ( _action == MyMoneySplit::ActionDividend || _action == MyMoneySplit::ActionYield ) { s1.setAccountId(_categoryid); s1.setShares(-value); s1.setValue(-value); // Split 2 will be the zero-amount investment split that serves to // mark this transaction as a cash dividend and note which stock account // it belongs to. MyMoneySplit s2; s2.setValue(0); s2.setShares(0); s2.setAction(_action); s2.setAccountId(_stockaccountid); addSplit(s2); MyMoneySplit s3; s3.setAccountId(_transferid); s3.setShares(value); s3.setValue(value); addSplit(s3); } else if ( _action == MyMoneySplit::ActionBuyShares ) { s1.setShares(_shares); s1.setAction(MyMoneySplit::ActionBuyShares); MyMoneySplit s3; s3.setAccountId(_transferid); s3.setShares(-value); s3.setValue(-value); addSplit(s3); } addSplit(s1); //kdDebug(2) << "created transaction, now adding..." << endl; MyMoneyFileTransaction ft; file->addTransaction(*this); //kdDebug(2) << "updating price..." << endl; // update the price, while we're here QString stockid = stockaccount.currencyId(); QString basecurrencyid = file->baseCurrency().id(); MyMoneyPrice price = file->price( stockid, basecurrencyid, _date, true ); if ( !price.isValid() ) { MyMoneyPrice newprice( stockid, basecurrencyid, _date, _price, "test" ); file->addPrice(newprice); } ft.commit(); //kdDebug(2) << "successfully added " << id() << endl; }
void MyMoneyForecast::addScheduledTransactions (void) { MyMoneyFile* file = MyMoneyFile::instance(); // now process all the schedules that may have an impact QValueList<MyMoneySchedule> schedule; schedule = file->scheduleList("", MyMoneySchedule::TYPE_ANY, MyMoneySchedule::OCCUR_ANY, MyMoneySchedule::STYPE_ANY, QDate(), forecastEndDate()); if(schedule.count() > 0) { QValueList<MyMoneySchedule>::Iterator it; do { qBubbleSort(schedule); it = schedule.begin(); if(it == schedule.end()) break; if((*it).isFinished()) { schedule.erase(it); continue; } QDate date = (*it).nextPayment((*it).lastPayment()); if(!date.isValid()) { schedule.remove(it); continue; } QDate nextDate = (*it).adjustedNextPayment((*it).adjustedDate((*it).lastPayment(), (*it).weekendOption())); if (nextDate > forecastEndDate()) { // We're done with this schedule, let's move on to the next schedule.remove(it); continue; } // found the next schedule. process it MyMoneyAccount acc = (*it).account(); if(!acc.id().isEmpty()) { try { if(acc.accountType() != MyMoneyAccount::Investment) { MyMoneyTransaction t = (*it).transaction(); // only process the entry, if it is still active if(!(*it).isFinished() && nextDate != QDate()) { // make sure we have all 'starting balances' so that the autocalc works QValueList<MyMoneySplit>::const_iterator it_s; QMap<QString, MyMoneyMoney> balanceMap; for(it_s = t.splits().begin(); it_s != t.splits().end(); ++it_s ) { MyMoneyAccount acc = file->account((*it_s).accountId()); if(isForecastAccount(acc)) { // collect all overdues on the first day QDate forecastDate = nextDate; if(QDate::currentDate() >= nextDate) forecastDate = QDate::currentDate().addDays(1); dailyBalances balance; balance = m_accountList[acc.id()]; for(QDate f_day = QDate::currentDate(); f_day < forecastDate; ) { balanceMap[acc.id()] += m_accountList[acc.id()][f_day]; f_day = f_day.addDays(1); } } } // take care of the autoCalc stuff calculateAutoLoan(*it, t, balanceMap); // now add the splits to the balances for(it_s = t.splits().begin(); it_s != t.splits().end(); ++it_s ) { MyMoneyAccount acc = file->account((*it_s).accountId()); if(isForecastAccount(acc)) { dailyBalances balance; balance = m_accountList[acc.id()]; //int offset = QDate::currentDate().daysTo(nextDate); //if(offset <= 0) { // collect all overdues on the first day // offset = 1; //} // collect all overdues on the first day QDate forecastDate = nextDate; if(QDate::currentDate() >= nextDate) forecastDate = QDate::currentDate().addDays(1); if(acc.accountType() == MyMoneyAccount::Income) { balance[forecastDate] += ((*it_s).shares() * MyMoneyMoney(-1, 1)); } else { balance[forecastDate] += (*it_s).shares(); } m_accountList[acc.id()] = balance; } } } } (*it).setLastPayment(date); } catch(MyMoneyException* e) { kdDebug(2) << __func__ << " Schedule " << (*it).id() << " (" << (*it).name() << "): " << e->what() << endl; schedule.remove(it); delete e; } } else { // remove schedule from list schedule.remove(it); } } while(1); } #if 0 { s << "\n\nAdded scheduled transactions\n"; QMap<QString, dailyBalances>::Iterator it_a; QMap<QString, QString>::ConstIterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); it_a = m_accountList.find(*it_n); s << "\"" << acc.name() << "\","; for(int i = 0; i < 90; ++i) { s << "\"" << (*it_a)[i].formatMoney("") << "\","; } s << "\n"; } } #endif }
const QString CsvUtil::checkCategory(const QString& name, const MyMoneyMoney& value, const MyMoneyMoney& value2) { // Borrowed from MyMoneyQifReader::checkCategory() QString accountId; MyMoneyFile *file = MyMoneyFile::instance(); MyMoneyAccount account; bool found = true; if (!name.isEmpty()) { // The category might be constructed with an arbitraty depth (number of // colon delimited fields). We try to find a parent account within this // hierarchy by searching the following sequence: // // aaaa:bbbb:cccc:ddddd // // 1. search aaaa:bbbb:cccc:dddd, create nothing // 2. search aaaa:bbbb:cccc , create dddd // 3. search aaaa:bbbb , create cccc:dddd // 4. search aaaa , create bbbb:cccc:dddd // 5. don't search , create aaaa:bbbb:cccc:dddd account.setName(name); QString accName; // part to be created (right side in above list) QString parent(name); // a possible parent part (left side in above list) do { accountId = file->categoryToAccount(parent); if (accountId.isEmpty()) { found = false; // prepare next step if (!accName.isEmpty()) accName.prepend(':'); accName.prepend(parent.section(':', -1)); account.setName(accName); parent = parent.section(':', 0, -2); } else if (!accName.isEmpty()) { account.setParentAccountId(accountId); } } while (!parent.isEmpty() && accountId.isEmpty()); // if we did not find the category, we create it if (!found) { MyMoneyAccount parent; if (account.parentAccountId().isEmpty()) { if (!value.isNegative() && value2.isNegative()) parent = file->income(); else parent = file->expense(); } else { parent = file->account(account.parentAccountId()); } account.setAccountType((!value.isNegative() && value2.isNegative()) ? MyMoneyAccount::Income : MyMoneyAccount::Expense); MyMoneyAccount brokerage; // clear out the parent id, because createAccount() does not like that account.setParentAccountId(QString()); createAccount(account, parent, brokerage, MyMoneyMoney()); accountId = account.id(); } } return accountId; }
void KForecastView::loadSummaryView() { MyMoneyForecast forecast = KMyMoneyGlobalSettings::forecast(); QList<MyMoneyAccount> accList; int dropMinimum; int dropZero; MyMoneyFile* file = MyMoneyFile::instance(); //get the settings from current page forecast.setForecastDays(m_forecastDays->value()); forecast.setAccountsCycle(m_accountsCycle->value()); forecast.setBeginForecastDay(m_beginDay->value()); forecast.setForecastCycles(m_forecastCycles->value()); forecast.setHistoryMethod(m_historyMethod->checkedId()); forecast.doForecast(); //add columns QStringList headerLabels; headerLabels << i18n("Account"); headerLabels << i18nc("Today's forecast", "Current"); //if beginning of forecast is today, set the begin day to next cycle to avoid repeating the first cycle int daysToBeginDay; if (QDate::currentDate() < forecast.beginForecastDate()) { daysToBeginDay = QDate::currentDate().daysTo(forecast.beginForecastDate()); } else { daysToBeginDay = forecast.accountsCycle(); } for (int i = 0; ((i*forecast.accountsCycle()) + daysToBeginDay) <= forecast.forecastDays(); ++i) { int intervalDays = ((i * forecast.accountsCycle()) + daysToBeginDay); headerLabels << i18np("1 day", "%1 days", intervalDays); } //add variation columns headerLabels << i18n("Total variation"); m_summaryList->clear(); //set the columns m_summaryList->setHeaderLabels(headerLabels); m_summaryList->setIconSize(QSize(22, 22)); m_summaryList->setSortingEnabled(true); m_summaryList->sortByColumn(0, Qt::AscendingOrder); //add default rows addTotalRow(m_summaryList, forecast); addAssetLiabilityRows(forecast); loadAccounts(forecast, file->asset(), m_assetItem, eSummary); loadAccounts(forecast, file->liability(), m_liabilityItem, eSummary); adjustHeadersAndResizeToContents(m_summaryList); //Add comments to the advice list m_adviceText->clear(); //Get all accounts of the right type to calculate forecast m_nameIdx.clear(); accList = forecast.accountList(); QList<MyMoneyAccount>::const_iterator accList_t = accList.constBegin(); for (; accList_t != accList.constEnd(); ++accList_t) { MyMoneyAccount acc = *accList_t; if (m_nameIdx[acc.id()] != acc.id()) { //Check if the account is there m_nameIdx[acc.id()] = acc.id(); } } QMap<QString, QString>::ConstIterator it_nc; for (it_nc = m_nameIdx.constBegin(); it_nc != m_nameIdx.constEnd(); ++it_nc) { const MyMoneyAccount& acc = file->account(*it_nc); MyMoneySecurity currency; //change currency to deep currency if account is an investment if (acc.isInvest()) { MyMoneySecurity underSecurity = file->security(acc.currencyId()); currency = file->security(underSecurity.tradingCurrency()); } else { currency = file->security(acc.currencyId()); } //Check if the account is going to be below zero or below the minimal balance in the forecast period QString minimumBalance = acc.value("minimumBalance"); MyMoneyMoney minBalance = MyMoneyMoney(minimumBalance); //Check if the account is going to be below minimal balance dropMinimum = forecast.daysToMinimumBalance(acc); //Check if the account is going to be below zero in the future dropZero = forecast.daysToZeroBalance(acc); // spit out possible warnings QString msg; // if a minimum balance has been specified, an appropriate warning will // only be shown, if the drop below 0 is on a different day or not present if (dropMinimum != -1 && !minBalance.isZero() && (dropMinimum < dropZero || dropZero == -1)) { switch (dropMinimum) { case -1: break; case 0: msg = QString("<font color=\"%1\">").arg(KMyMoneyGlobalSettings::listNegativeValueColor().name()); msg += i18n("The balance of %1 is below the minimum balance %2 today.", acc.name(), MyMoneyUtils::formatMoney(minBalance, acc, currency)); msg += QString("</font>"); break; default: msg = QString("<font color=\"%1\">").arg(KMyMoneyGlobalSettings::listNegativeValueColor().name()); msg += i18np("The balance of %2 will drop below the minimum balance %3 in %1 day.", "The balance of %2 will drop below the minimum balance %3 in %1 days.", dropMinimum - 1, acc.name(), MyMoneyUtils::formatMoney(minBalance, acc, currency)); msg += QString("</font>"); } if (!msg.isEmpty()) { m_adviceText->append(msg); } } // a drop below zero is always shown msg.clear(); switch (dropZero) { case -1: break; case 0: if (acc.accountGroup() == MyMoneyAccount::Asset) { msg = QString("<font color=\"%1\">").arg(KMyMoneyGlobalSettings::listNegativeValueColor().name()); msg += i18n("The balance of %1 is below %2 today.", acc.name(), MyMoneyUtils::formatMoney(MyMoneyMoney(), acc, currency)); msg += QString("</font>"); break; } if (acc.accountGroup() == MyMoneyAccount::Liability) { msg = i18n("The balance of %1 is above %2 today.", acc.name(), MyMoneyUtils::formatMoney(MyMoneyMoney(), acc, currency)); break; } break; default: if (acc.accountGroup() == MyMoneyAccount::Asset) { msg = QString("<font color=\"%1\">").arg(KMyMoneyGlobalSettings::listNegativeValueColor().name()); msg += i18np("The balance of %2 will drop below %3 in %1 day.", "The balance of %2 will drop below %3 in %1 days.", dropZero, acc.name(), MyMoneyUtils::formatMoney(MyMoneyMoney(), acc, currency)); msg += QString("</font>"); break; } if (acc.accountGroup() == MyMoneyAccount::Liability) { msg = i18np("The balance of %2 will raise above %3 in %1 day.", "The balance of %2 will raise above %3 in %1 days.", dropZero, acc.name(), MyMoneyUtils::formatMoney(MyMoneyMoney(), acc, currency)); break; } } if (!msg.isEmpty()) { m_adviceText->append(msg); } //advice about trends msg.clear(); MyMoneyMoney accCycleVariation = forecast.accountCycleVariation(acc); if (accCycleVariation < MyMoneyMoney()) { msg = QString("<font color=\"%1\">").arg(KMyMoneyGlobalSettings::listNegativeValueColor().name()); msg += i18n("The account %1 is decreasing %2 per cycle.", acc.name(), MyMoneyUtils::formatMoney(accCycleVariation, acc, currency)); msg += QString("</font>"); } if (!msg.isEmpty()) { m_adviceText->append(msg); } } m_adviceText->show(); }
void MyMoneyForecast::calculateAccountTrendList() { MyMoneyFile* file = MyMoneyFile::instance(); int auxForecastTerms; int totalWeight = 0; //Calculate account trends QMap<QString, QString>::Iterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); m_accountTrendList[acc.id()][0] = MyMoneyMoney(0,1); // for today, the trend is 0 auxForecastTerms = forecastCycles(); if(skipOpeningDate()) { QDate openingDate; if(acc.accountType() == MyMoneyAccount::Stock) { MyMoneyAccount parentAccount = file->account(acc.parentAccountId()); openingDate = parentAccount.openingDate(); } else { openingDate = acc.openingDate(); } if(openingDate > historyStartDate() ) { //if acc opened after forecast period auxForecastTerms = 1 + ((openingDate.daysTo(historyEndDate()) + 1)/ accountsCycle()); // set forecastTerms to a lower value, to calculate only based on how long this account was opened } } switch (historyMethod()) { //moving average case 0: { for(int t_day = 1; t_day <= accountsCycle(); t_day++) m_accountTrendList[acc.id()][t_day] = accountMovingAverage(acc, t_day, auxForecastTerms); //moving average break; } //weighted moving average case 1: { //calculate total weight for moving average if(auxForecastTerms == forecastCycles()) { totalWeight = (auxForecastTerms * (auxForecastTerms + 1))/2; //totalWeight is the triangular number of auxForecastTerms } else { //if only taking a few periods, totalWeight is the sum of the weight for most recent periods for(int i = 1, w = forecastCycles(); i <= auxForecastTerms; ++i, --w) totalWeight += w; } for(int t_day = 1; t_day <= accountsCycle(); t_day++) m_accountTrendList[acc.id()][t_day] = accountWeightedMovingAverage(acc, t_day, totalWeight); break; } case 2: { //calculate mean term MyMoneyMoney meanTerms = MyMoneyMoney((auxForecastTerms * (auxForecastTerms + 1))/2, 1) / MyMoneyMoney(auxForecastTerms, 1); for(int t_day = 1; t_day <= accountsCycle(); t_day++) m_accountTrendList[acc.id()][t_day] = accountLinearRegression(acc, t_day, auxForecastTerms, meanTerms); break; } default: break; } } }
void MyMoneyForecast::setStartingBalance(const MyMoneyAccount &acc) { MyMoneyFile* file = MyMoneyFile::instance(); //Get current account balance if ( acc.isInvest() ) { //investments require special treatment //get the security id of that account MyMoneySecurity undersecurity = file->security ( acc.currencyId() ); //only do it if the security is not an actual currency if ( ! undersecurity.isCurrency() ) { //set the default value MyMoneyMoney rate = MyMoneyMoney ( 1, 1 ); //get te MyMoneyPrice price = file->price ( undersecurity.id(), undersecurity.tradingCurrency(), QDate::currentDate() ); if ( price.isValid() ) { rate = price.rate ( undersecurity.tradingCurrency() ); } m_accountList[acc.id()][QDate::currentDate()] = file->balance(acc.id(), QDate::currentDate()) * rate; } } else { m_accountList[acc.id()][QDate::currentDate()] = file->balance(acc.id(), QDate::currentDate()); } //if the method is linear regression, we have to add the opening balance to m_accountListPast if(forecastMethod() == eHistoric && historyMethod() == 2) { //FIXME workaround for stock opening dates QDate openingDate; if(acc.accountType() == MyMoneyAccount::Stock) { MyMoneyAccount parentAccount = file->account(acc.parentAccountId()); openingDate = parentAccount.openingDate(); } else { openingDate = acc.openingDate(); } //add opening balance only if it opened after the history start if(openingDate >= historyStartDate()) { MyMoneyMoney openingBalance; openingBalance = file->balance(acc.id(), openingDate); //calculate running sum for(QDate it_date = openingDate; it_date <= historyEndDate(); it_date = it_date.addDays(1) ) { //investments require special treatment if ( acc.isInvest() ) { //get the security id of that account MyMoneySecurity undersecurity = file->security ( acc.currencyId() ); //only do it if the security is not an actual currency if ( ! undersecurity.isCurrency() ) { //set the default value MyMoneyMoney rate = MyMoneyMoney ( 1, 1 ); //get the rate for that specific date MyMoneyPrice price = file->price ( undersecurity.id(), undersecurity.tradingCurrency(), it_date ); if ( price.isValid() ) { rate = price.rate ( undersecurity.tradingCurrency() ); } m_accountListPast[acc.id()][it_date] += openingBalance * rate; } } else { m_accountListPast[acc.id()][it_date] += openingBalance; } } } } }
void KNewInvestmentWizard::createObjects(const QString& parentId) { MyMoneyFile* file = MyMoneyFile::instance(); QValueList<MyMoneySecurity> list = MyMoneyFile::instance()->securityList(); QValueList<MyMoneySecurity>::ConstIterator it; MyMoneySecurity::eSECURITYTYPE type = KMyMoneyUtils::stringToSecurity(m_securityType->currentText()); MyMoneyFileTransaction ft; try { // update all relevant attributes only, if we create a stock // account and the security is unknown or we modifiy the security MyMoneySecurity newSecurity(m_security); newSecurity.setName(m_investmentName->text()); newSecurity.setTradingSymbol(m_investmentSymbol->text()); newSecurity.setTradingMarket(m_tradingMarket->currentText()); newSecurity.setSmallestAccountFraction(m_fraction->value()); newSecurity.setTradingCurrency(m_tradingCurrencyEdit->security().id()); newSecurity.setSecurityType(type); newSecurity.deletePair("kmm-online-source"); newSecurity.deletePair("kmm-online-quote-system"); newSecurity.deletePair("kmm-online-factor"); newSecurity.deletePair("kmm-security-id"); if(!m_onlineSourceCombo->currentText().isEmpty()) { if (m_useFinanceQuote->isChecked()) { FinanceQuoteProcess p; newSecurity.setValue("kmm-online-quote-system", "Finance::Quote"); newSecurity.setValue("kmm-online-source", p.crypticName(m_onlineSourceCombo->currentText())); }else{ newSecurity.setValue("kmm-online-source", m_onlineSourceCombo->currentText()); } } if(m_onlineFactor->isEnabled() && (m_onlineFactor->value() != MyMoneyMoney(1,1))) newSecurity.setValue("kmm-online-factor", m_onlineFactor->value().toString()); if(!m_investmentIdentification->text().isEmpty()) newSecurity.setValue("kmm-security-id", m_investmentIdentification->text()); if(m_security.id().isEmpty() || newSecurity != m_security) { m_security = newSecurity; // add or update it if(m_security.id().isEmpty()) { file->addSecurity(m_security); } else { file->modifySecurity(m_security); } } if(m_createAccount) { // now that the security exists, we can add the account to store it m_account.setName(m_investmentName->text()); if(m_account.accountType() == MyMoneyAccount::UnknownAccountType) m_account.setAccountType(MyMoneyAccount::Stock); m_account.setCurrencyId(m_security.id()); switch(m_priceMode->currentItem()) { case 0: m_account.deletePair("priceMode"); break; case 1: case 2: m_account.setValue("priceMode", QString("%1").arg(m_priceMode->currentItem())); break; } if(m_account.id().isEmpty()) { MyMoneyAccount parent = file->account(parentId); file->addAccount(m_account, parent); } else file->modifyAccount(m_account); } ft.commit(); } catch(MyMoneyException* e) { KMessageBox::detailedSorry(0, i18n("Unable to create all objects for the investment"), QString("%1 caugt in %2:%3").arg(e->what()).arg(e->file()).arg(e->line())); delete e; } }
void MyMoneyForecast::pastTransactions() { MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyTransactionFilter filter; filter.setDateFilter(historyStartDate(), historyEndDate()); filter.setReportAllSplits(false); QValueList<MyMoneyTransaction> transactions = file->transactionList(filter); QValueList<MyMoneyTransaction>::const_iterator it_t = transactions.begin(); //Check past transactions for(; it_t != transactions.end(); ++it_t ) { const QValueList<MyMoneySplit>& splits = (*it_t).splits(); QValueList<MyMoneySplit>::const_iterator it_s = splits.begin(); for(; it_s != splits.end(); ++it_s ) { if(!(*it_s).shares().isZero()) { MyMoneyAccount acc = file->account((*it_s).accountId()); //workaround for stock accounts which have faulty opening dates QDate openingDate; if(acc.accountType() == MyMoneyAccount::Stock) { MyMoneyAccount parentAccount = file->account(acc.parentAccountId()); openingDate = parentAccount.openingDate(); } else { openingDate = acc.openingDate(); } if(isForecastAccount(acc) //If it is one of the accounts we are checking, add the amount of the transaction && ( (openingDate < (*it_t).postDate() && skipOpeningDate()) || !skipOpeningDate() ) ){ //don't take the opening day of the account to calculate balance dailyBalances balance; //FIXME deal with leap years balance = m_accountListPast[acc.id()]; if(acc.accountType() == MyMoneyAccount::Income) {//if it is income, the balance is stored as negative number balance[(*it_t).postDate()] += ((*it_s).shares() * MyMoneyMoney(-1, 1)); } else { balance[(*it_t).postDate()] += (*it_s).shares(); } // check if this is a new account for us m_accountListPast[acc.id()] = balance; } } } } //purge those accounts with no transactions on the period if(isIncludingUnusedAccounts() == false) purgeForecastAccountsList(m_accountListPast); //calculate running sum QMap<QString, QString>::Iterator it_n; for(it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n) { MyMoneyAccount acc = file->account(*it_n); m_accountListPast[acc.id()][historyStartDate().addDays(-1)] = file->balance(acc.id(), historyStartDate().addDays(-1)); for(QDate it_date = historyStartDate(); it_date <= historyEndDate(); ) { m_accountListPast[acc.id()][it_date] += m_accountListPast[acc.id()][it_date.addDays(-1)]; //Running sum it_date = it_date.addDays(1); } } //adjust value of investments to deep currency for ( it_n = m_nameIdx.begin(); it_n != m_nameIdx.end(); ++it_n ) { MyMoneyAccount acc = file->account ( *it_n ); if ( acc.isInvest() ) { //get the id of the security for that account MyMoneySecurity undersecurity = file->security ( acc.currencyId() ); if ( ! undersecurity.isCurrency() ) //only do it if the security is not an actual currency { MyMoneyMoney rate = MyMoneyMoney ( 1, 1 ); //set the default value MyMoneyPrice price; for ( QDate it_date = historyStartDate().addDays(-1) ; it_date <= historyEndDate();) { //get the price for the tradingCurrency that day price = file->price ( undersecurity.id(), undersecurity.tradingCurrency(), it_date ); if ( price.isValid() ) { rate = price.rate ( undersecurity.tradingCurrency() ); } //value is the amount of shares multiplied by the rate of the deep currency m_accountListPast[acc.id() ][it_date] = m_accountListPast[acc.id() ][it_date] * rate; it_date = it_date.addDays(1); } } } } }
void MyMoneyForecast::createBudget ( MyMoneyBudget& budget, QDate historyStart, QDate historyEnd, QDate budgetStart, QDate budgetEnd, const bool returnBudget ) { // clear all data except the id and name QString name = budget.name(); budget = MyMoneyBudget(budget.id(), MyMoneyBudget()); budget.setName(name); //check parameters if ( historyStart > historyEnd || budgetStart > budgetEnd || budgetStart <= historyEnd ) { throw new MYMONEYEXCEPTION ( "Illegal parameters when trying to create budget" ); } //get forecast method int fMethod = forecastMethod(); //set start date to 1st of month and end dates to last day of month, since we deal with full months in budget historyStart = QDate ( historyStart.year(), historyStart.month(), 1 ); historyEnd = QDate ( historyEnd.year(), historyEnd.month(), historyEnd.daysInMonth() ); budgetStart = QDate ( budgetStart.year(), budgetStart.month(), 1 ); budgetEnd = QDate ( budgetEnd.year(), budgetEnd.month(), budgetEnd.daysInMonth() ); //set forecast parameters setHistoryStartDate ( historyStart ); setHistoryEndDate ( historyEnd ); setForecastStartDate ( budgetStart ); setForecastEndDate ( budgetEnd ); setForecastDays ( budgetStart.daysTo ( budgetEnd ) + 1 ); if ( budgetStart.daysTo ( budgetEnd ) > historyStart.daysTo ( historyEnd ) ) { //if history period is shorter than budget, use that one as the trend length setAccountsCycle ( historyStart.daysTo ( historyEnd ) ); //we set the accountsCycle to the base timeframe we will use to calculate the average (eg. 180 days, 365, etc) } else { //if one timeframe is larger than the other, but not enough to be 1 time larger, we take the lowest value setAccountsCycle ( budgetStart.daysTo ( budgetEnd ) ); } setForecastCycles ( ( historyStart.daysTo ( historyEnd ) / accountsCycle() ) ); if ( forecastCycles() == 0 ) //the cycles must be at least 1 setForecastCycles ( 1 ); //do not skip opening date setSkipOpeningDate ( false ); //clear and set accounts list we are going to use. Categories, in this case m_nameIdx.clear(); setBudgetAccountList(); //calculate budget according to forecast method switch(fMethod) { case eScheduled: doFutureScheduledForecast(); calculateScheduledMonthlyBalances(); break; case eHistoric: pastTransactions(); //get all transactions for history period calculateAccountTrendList(); calculateHistoricMonthlyBalances(); //add all balances of each month and put at the 1st day of each month break; default: break; } //flag the forecast as done m_forecastDone = true; //only fill the budget if it is going to be used if ( returnBudget ) { //setup the budget itself MyMoneyFile* file = MyMoneyFile::instance(); budget.setBudgetStart ( budgetStart ); //go through all the accounts and add them to budget QMap<QString, QString>::ConstIterator it_nc; for ( it_nc = m_nameIdx.begin(); it_nc != m_nameIdx.end(); ++it_nc ) { MyMoneyAccount acc = file->account ( *it_nc ); MyMoneyBudget::AccountGroup budgetAcc; budgetAcc.setId ( acc.id() ); budgetAcc.setBudgetLevel ( MyMoneyBudget::AccountGroup::eMonthByMonth ); for ( QDate f_date = forecastStartDate(); f_date <= forecastEndDate(); ) { MyMoneyBudget::PeriodGroup period; //add period to budget account period.setStartDate ( f_date ); period.setAmount ( forecastBalance ( acc, f_date ) ); budgetAcc.addPeriod ( f_date, period ); //next month f_date = f_date.addMonths ( 1 ); } //add budget account to budget budget.setAccount ( budgetAcc, acc.id() ); } } }
void KNewAccountDlg::initParentWidget(QString parentId, const QString& accountId) { MyMoneyFile *file = MyMoneyFile::instance(); MyMoneyAccount liabilityAccount = file->liability(); MyMoneyAccount assetAccount = file->asset(); MyMoneyAccount expenseAccount = file->expense(); MyMoneyAccount incomeAccount = file->income(); MyMoneyAccount equityAccount = file->equity(); m_parentItem = 0; m_accountItem = 0; // Determine the parent account try { m_parentAccount = file->account(parentId); } catch (MyMoneyException *e) { m_bSelectedParentAccount = false; m_parentAccount = MyMoneyAccount(); if(m_account.accountType() != MyMoneyAccount::UnknownAccountType) { parentAccount(); parentId = m_parentAccount.id(); } delete e; } m_bSelectedParentAccount = true; // extract the account type from the combo box MyMoneyAccount::accountTypeE type; MyMoneyAccount::accountTypeE groupType; type = KMyMoneyUtils::stringToAccountType(typeCombo->currentText()); groupType = MyMoneyAccount::accountGroup(type); m_qlistviewParentAccounts->clear(); // Now scan all 4 account roots to load the list and mark the parent try { if (!m_categoryEditor) { if(groupType == MyMoneyAccount::Asset || type == MyMoneyAccount::Loan) { // Asset KMyMoneyAccountTreeBaseItem *assetTopLevelAccount = new KMyMoneyAccountTreeItem(m_qlistviewParentAccounts, assetAccount); if(m_parentAccount.id().isEmpty()) { m_parentAccount = assetAccount; parentId = m_parentAccount.id(); } if (parentId == assetAccount.id()) m_parentItem = assetTopLevelAccount; assetTopLevelAccount->setOpen(true); for ( QStringList::ConstIterator it = assetAccount.accountList().begin(); it != assetAccount.accountList().end(); ++it ) { MyMoneyAccount acc = file->account(*it); if(acc.isClosed()) continue; KMyMoneyAccountTreeBaseItem *accountItem = new KMyMoneyAccountTreeItem(assetTopLevelAccount, acc); if(parentId == acc.id()) { m_parentItem = accountItem; } else if(accountId == acc.id()) { if(m_isEditing) accountItem->setSelectable(false); m_accountItem = accountItem; } QStringList subAccounts = acc.accountList(); if (subAccounts.count() >= 1) { showSubAccounts(subAccounts, accountItem, parentId, acc.id()); } } } if(groupType == MyMoneyAccount::Liability) { // Liability KMyMoneyAccountTreeBaseItem *liabilityTopLevelAccount = new KMyMoneyAccountTreeItem(m_qlistviewParentAccounts, liabilityAccount); if(m_parentAccount.id().isEmpty()) { m_parentAccount = liabilityAccount; parentId = m_parentAccount.id(); } if (parentId == liabilityAccount.id()) m_parentItem = liabilityTopLevelAccount; liabilityTopLevelAccount->setOpen(true); for ( QStringList::ConstIterator it = liabilityAccount.accountList().begin(); it != liabilityAccount.accountList().end(); ++it ) { MyMoneyAccount acc = file->account(*it); if(acc.isClosed()) continue; KMyMoneyAccountTreeBaseItem *accountItem = new KMyMoneyAccountTreeItem(liabilityTopLevelAccount, acc); if(parentId == acc.id()) { m_parentItem = accountItem; } else if(accountId == acc.id()) { if(m_isEditing) accountItem->setSelectable(false); m_accountItem = accountItem; } QStringList subAccounts = acc.accountList(); if (subAccounts.count() >= 1) { showSubAccounts(subAccounts, accountItem, parentId, acc.id()); } } } } else { if(groupType == MyMoneyAccount::Income) { // Income KMyMoneyAccountTreeBaseItem *incomeTopLevelAccount = new KMyMoneyAccountTreeItem(m_qlistviewParentAccounts, incomeAccount); if(m_parentAccount.id().isEmpty()) { m_parentAccount = incomeAccount; parentId = m_parentAccount.id(); } if (parentId == incomeAccount.id()) m_parentItem = incomeTopLevelAccount; incomeTopLevelAccount->setOpen(true); for ( QStringList::ConstIterator it = incomeAccount.accountList().begin(); it != incomeAccount.accountList().end(); ++it ) { KMyMoneyAccountTreeBaseItem *accountItem = new KMyMoneyAccountTreeItem(incomeTopLevelAccount, file->account(*it)); QString id = file->account(*it).id(); if(parentId == id) { m_parentItem = accountItem; } else if(accountId == id) { if(m_isEditing) accountItem->setSelectable(false); m_accountItem = accountItem; } QStringList subAccounts = file->account(*it).accountList(); if (subAccounts.count() >= 1) { showSubAccounts(subAccounts, accountItem, parentId, accountId); } } } if(groupType == MyMoneyAccount::Expense) { // Expense KMyMoneyAccountTreeBaseItem *expenseTopLevelAccount = new KMyMoneyAccountTreeItem(m_qlistviewParentAccounts, expenseAccount); if(m_parentAccount.id().isEmpty()) { m_parentAccount = expenseAccount; parentId = m_parentAccount.id(); } if (parentId == expenseAccount.id()) m_parentItem = expenseTopLevelAccount; expenseTopLevelAccount->setOpen(true); for ( QStringList::ConstIterator it = expenseAccount.accountList().begin(); it != expenseAccount.accountList().end(); ++it ) { KMyMoneyAccountTreeBaseItem *accountItem = new KMyMoneyAccountTreeItem(expenseTopLevelAccount, file->account(*it)); QString id = file->account(*it).id(); if(parentId == id) { m_parentItem = accountItem; } else if(accountId == id) { if(m_isEditing) accountItem->setSelectable(false); m_accountItem = accountItem; } QStringList subAccounts = file->account(*it).accountList(); if (subAccounts.count() >= 1) { showSubAccounts(subAccounts, accountItem, parentId, accountId); } } } } } catch (MyMoneyException *e) { qDebug("Exception in assets account refresh: %s", e->what().latin1()); delete e; } m_qlistviewParentAccounts->setColumnWidth(0, m_qlistviewParentAccounts->width()); if (m_parentItem) { m_subAccountLabel->setText(i18n("Is a sub account of %1").arg(m_parentAccount.name())); m_parentItem->setOpen(true); m_qlistviewParentAccounts->setSelected(m_parentItem, true); } m_qlistviewParentAccounts->setEnabled(true); }
void KForecastView::loadAdvancedView() { MyMoneyFile* file = MyMoneyFile::instance(); QList<MyMoneyAccount> accList; MyMoneySecurity baseCurrency = file->baseCurrency(); MyMoneyForecast forecast = KMyMoneyGlobalSettings::forecast(); int daysToBeginDay; //get the settings from current page forecast.setForecastDays(m_forecastDays->value()); forecast.setAccountsCycle(m_accountsCycle->value()); forecast.setBeginForecastDay(m_beginDay->value()); forecast.setForecastCycles(m_forecastCycles->value()); forecast.setHistoryMethod(m_historyMethod->checkedId()); forecast.doForecast(); //Get all accounts of the right type to calculate forecast m_nameIdx.clear(); accList = forecast.accountList(); QList<MyMoneyAccount>::const_iterator accList_t = accList.constBegin(); for (; accList_t != accList.constEnd(); ++accList_t) { MyMoneyAccount acc = *accList_t; if (m_nameIdx[acc.id()] != acc.id()) { //Check if the account is there m_nameIdx[acc.id()] = acc.id(); } } //clear the list, including columns m_advancedList->clear(); m_advancedList->setColumnCount(0); m_advancedList->setIconSize(QSize(22, 22)); QStringList headerLabels; //add first column of both lists headerLabels << i18n("Account"); //if beginning of forecast is today, set the begin day to next cycle to avoid repeating the first cycle if (QDate::currentDate() < forecast.beginForecastDate()) { daysToBeginDay = QDate::currentDate().daysTo(forecast.beginForecastDate()); } else { daysToBeginDay = forecast.accountsCycle(); } //add columns for (int i = 1; ((i * forecast.accountsCycle()) + daysToBeginDay) <= forecast.forecastDays(); ++i) { headerLabels << i18n("Min Bal %1", i); headerLabels << i18n("Min Date %1", i); } for (int i = 1; ((i * forecast.accountsCycle()) + daysToBeginDay) <= forecast.forecastDays(); ++i) { headerLabels << i18n("Max Bal %1", i); headerLabels << i18n("Max Date %1", i); } headerLabels << i18nc("Average balance", "Average"); m_advancedList->setHeaderLabels(headerLabels); QTreeWidgetItem *advancedItem = 0; QMap<QString, QString>::ConstIterator it_nc; for (it_nc = m_nameIdx.constBegin(); it_nc != m_nameIdx.constEnd(); ++it_nc) { const MyMoneyAccount& acc = file->account(*it_nc); QString amount; MyMoneyMoney amountMM; MyMoneySecurity currency; //change currency to deep currency if account is an investment if (acc.isInvest()) { MyMoneySecurity underSecurity = file->security(acc.currencyId()); currency = file->security(underSecurity.tradingCurrency()); } else { currency = file->security(acc.currencyId()); } advancedItem = new QTreeWidgetItem(m_advancedList, advancedItem, false); advancedItem->setText(0, acc.name()); advancedItem->setIcon(0, acc.accountPixmap()); int it_c = 1; // iterator for the columns of the listview //get minimum balance list QList<QDate> minBalanceList = forecast.accountMinimumBalanceDateList(acc); QList<QDate>::Iterator t_min; for (t_min = minBalanceList.begin(); t_min != minBalanceList.end() ; ++t_min) { QDate minDate = *t_min; amountMM = forecast.forecastBalance(acc, minDate); amount = MyMoneyUtils::formatMoney(amountMM, acc, currency); advancedItem->setText(it_c, amount); advancedItem->setTextAlignment(it_c, Qt::AlignRight | Qt::AlignVCenter); if (amountMM.isNegative()) { advancedItem->setForeground(it_c, KMyMoneyGlobalSettings::listNegativeValueColor()); } it_c++; QString dateString = QLocale().toString(minDate, QLocale::ShortFormat); advancedItem->setText(it_c, dateString); advancedItem->setTextAlignment(it_c, Qt::AlignRight | Qt::AlignVCenter); if (amountMM.isNegative()) { advancedItem->setForeground(it_c, KMyMoneyGlobalSettings::listNegativeValueColor()); } it_c++; } //get maximum balance list QList<QDate> maxBalanceList = forecast.accountMaximumBalanceDateList(acc); QList<QDate>::Iterator t_max; for (t_max = maxBalanceList.begin(); t_max != maxBalanceList.end() ; ++t_max) { QDate maxDate = *t_max; amountMM = forecast.forecastBalance(acc, maxDate); amount = MyMoneyUtils::formatMoney(amountMM, acc, currency); advancedItem->setText(it_c, amount); advancedItem->setTextAlignment(it_c, Qt::AlignRight | Qt::AlignVCenter); if (amountMM.isNegative()) { advancedItem->setForeground(it_c, KMyMoneyGlobalSettings::listNegativeValueColor()); } it_c++; QString dateString = QLocale().toString(maxDate, QLocale::ShortFormat); advancedItem->setText(it_c, dateString); advancedItem->setTextAlignment(it_c, Qt::AlignRight | Qt::AlignVCenter); if (amountMM.isNegative()) { advancedItem->setForeground(it_c, KMyMoneyGlobalSettings::listNegativeValueColor()); } it_c++; } //get average balance amountMM = forecast.accountAverageBalance(acc); amount = MyMoneyUtils::formatMoney(amountMM, acc, currency); advancedItem->setText(it_c, amount); advancedItem->setTextAlignment(it_c, Qt::AlignRight | Qt::AlignVCenter); if (amountMM.isNegative()) { advancedItem->setForeground(it_c, KMyMoneyGlobalSettings::listNegativeValueColor()); } it_c++; } // make sure all data is shown adjustHeadersAndResizeToContents(m_advancedList); m_advancedList->show(); }