MyMoneyMoney ReportAccount::deepCurrencyPrice(const QDate& date, bool exactDate) const { DEBUG_ENTER(Q_FUNC_INFO); MyMoneyMoney result(1, 1); MyMoneyFile* file = MyMoneyFile::instance(); MyMoneySecurity undersecurity = file->security(currencyId()); if (! undersecurity.isCurrency()) { const MyMoneyPrice &price = file->price(undersecurity.id(), undersecurity.tradingCurrency(), date, exactDate); if (price.isValid()) { result = price.rate(undersecurity.tradingCurrency()); DEBUG_OUTPUT(QString("Converting under %1 to deep %2, price on %3 is %4") .arg(undersecurity.name()) .arg(file->security(undersecurity.tradingCurrency()).name()) .arg(date.toString()) .arg(result.toDouble())); } else { DEBUG_OUTPUT(QString("No price to convert under %1 to deep %2 on %3") .arg(undersecurity.name()) .arg(file->security(undersecurity.tradingCurrency()).name()) .arg(date.toString())); result = MyMoneyMoney(); } } return result; }
void KMyMoneyAccountTreeForecastItem::updateBudget() { MyMoneySecurity currency; MyMoneyMoney tAmountMM; MyMoneyFile* file = MyMoneyFile::instance(); int it_c = 1; // iterator for the columns of the listview QDate forecastDate = m_forecast.forecastStartDate(); if(m_account.isInvest()) { MyMoneySecurity underSecurity = file->security(m_account.currencyId()); currency = file->security(underSecurity.tradingCurrency()); } else { currency = file->security(m_account.currencyId()); } //iterate columns for(; forecastDate <= m_forecast.forecastEndDate(); forecastDate = forecastDate.addMonths(1), ++it_c) { MyMoneyMoney amountMM; amountMM = m_forecast.forecastBalance(m_account,forecastDate); if(m_account.accountType() == MyMoneyAccount::Expense) amountMM = -amountMM; tAmountMM += amountMM; setAmount(it_c, amountMM); setValue(it_c, amountMM, forecastDate); showAmount(it_c, amountMM, currency); } //set total column setAmount(it_c, tAmountMM); setValue(it_c, tAmountMM, m_forecast.forecastEndDate()); showAmount(it_c, tAmountMM, currency); }
void KMyMoneyAccountTreeForecastItem::updateDetailed() { QString amount; QString vAmount; MyMoneyMoney vAmountMM; MyMoneyFile* file = MyMoneyFile::instance(); MyMoneySecurity currency; if(m_account.isInvest()) { MyMoneySecurity underSecurity = file->security(m_account.currencyId()); currency = file->security(underSecurity.tradingCurrency()); } else { currency = file->security(m_account.currencyId()); } int it_c = 1; // iterator for the columns of the listview for(QDate forecastDate = QDate::currentDate(); forecastDate <= m_forecast.forecastEndDate(); ++it_c, forecastDate = forecastDate.addDays(1)) { MyMoneyMoney amountMM = m_forecast.forecastBalance(m_account, forecastDate); //calculate the balance in base currency for the total row setAmount(it_c, amountMM); setValue(it_c, amountMM, forecastDate); showAmount(it_c, amountMM, currency); } //calculate and add variation per cycle vAmountMM = m_forecast.accountTotalVariation(m_account); setAmount(it_c, vAmountMM); setValue(it_c, vAmountMM, m_forecast.forecastEndDate()); showAmount(it_c, vAmountMM, currency); }
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); } }
KInvestmentListItem::KInvestmentListItem(KListView* parent, const MyMoneyAccount& account) : KListViewItem(parent) { bColumn5Negative = false; bColumn6Negative = false; bColumn7Negative = false; bColumn8Negative = false; bColumn9Negative = false; m_account = account; m_listView = parent; MyMoneySecurity security; MyMoneyFile* file = MyMoneyFile::instance(); security = file->security(m_account.currencyId()); m_tradingCurrency = file->security(security.tradingCurrency()); int prec = MyMoneyMoney::denomToPrec(m_tradingCurrency.smallestAccountFraction()); QValueList<MyMoneyTransaction> transactionList; // FIXME PRICE // equity_price_history history = equity.priceHistory(); //column 0 (COLUMN_NAME_INDEX) is the name of the stock setText(COLUMN_NAME_INDEX, m_account.name()); //column 1 (COLUMN_SYMBOL_INDEX) is the ticker symbol setText(COLUMN_SYMBOL_INDEX, security.tradingSymbol()); //column 2 is the net value (price * quantity owned) MyMoneyPrice price = file->price(m_account.currencyId(), m_tradingCurrency.id()); if(price.isValid()) { setText(COLUMN_VALUE_INDEX, (file->balance(m_account.id()) * price.rate(m_tradingCurrency.id())).formatMoney(m_tradingCurrency.tradingSymbol(), prec)); } else { setText(COLUMN_VALUE_INDEX, "---"); } //column 3 (COLUMN_QUANTITY_INDEX) is the quantity of shares owned prec = MyMoneyMoney::denomToPrec(security.smallestAccountFraction()); setText(COLUMN_QUANTITY_INDEX, file->balance(m_account.id()).formatMoney("", prec)); //column 4 is the current price // Get the price precision from the configuration prec = KMyMoneyGlobalSettings::pricePrecision(); // prec = MyMoneyMoney::denomToPrec(m_tradingCurrency.smallestAccountFraction()); if(price.isValid()) { setText(COLUMN_PRICE_INDEX, price.rate(m_tradingCurrency.id()).formatMoney(m_tradingCurrency.tradingSymbol(), prec)); } else { setText(COLUMN_PRICE_INDEX, "---"); } }
/** * Fetch the trading currency of this account's currency * * @return The account's currency trading currency */ MyMoneySecurity ReportAccount::currency() const { MyMoneyFile* file = MyMoneyFile::instance(); // First, get the deep currency MyMoneySecurity deepcurrency = file->security(currencyId()); if (! deepcurrency.isCurrency()) deepcurrency = file->security(deepcurrency.tradingCurrency()); // Return the deep currency's ID return deepcurrency; }
void KForecastView::updateSummary(QTreeWidgetItem *item) { MyMoneyMoney amountMM; int it_c = 1; // iterator for the columns of the listview MyMoneyFile* file = MyMoneyFile::instance(); int daysToBeginDay; MyMoneyForecast forecast = item->data(0, ForecastRole).value<MyMoneyForecast>(); if (QDate::currentDate() < forecast.beginForecastDate()) { daysToBeginDay = QDate::currentDate().daysTo(forecast.beginForecastDate()); } else { daysToBeginDay = forecast.accountsCycle(); } MyMoneyAccount account = item->data(0, AccountRole).value<MyMoneyAccount>(); MyMoneySecurity currency; if (account.isInvest()) { MyMoneySecurity underSecurity = file->security(account.currencyId()); currency = file->security(underSecurity.tradingCurrency()); } else { currency = file->security(account.currencyId()); } //add current balance column QDate summaryDate = QDate::currentDate(); amountMM = forecast.forecastBalance(account, summaryDate); //calculate the balance in base currency for the total row setAmount(item, it_c, amountMM); setValue(item, it_c, amountMM, summaryDate); showAmount(item, it_c, amountMM, currency); it_c++; //iterate through all other columns for (QDate summaryDate = QDate::currentDate().addDays(daysToBeginDay); summaryDate <= forecast.forecastEndDate(); summaryDate = summaryDate.addDays(forecast.accountsCycle()), ++it_c) { amountMM = forecast.forecastBalance(account, summaryDate); //calculate the balance in base currency for the total row setAmount(item, it_c, amountMM); setValue(item, it_c, amountMM, summaryDate); showAmount(item, it_c, amountMM, currency); } //calculate and add variation per cycle setNegative(item, forecast.accountTotalVariation(account).isNegative()); setAmount(item, it_c, forecast.accountTotalVariation(account)); setValue(item, it_c, forecast.accountTotalVariation(account), forecast.forecastEndDate()); showAmount(item, it_c, forecast.accountTotalVariation(account), currency); }
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 &) { } }
void KEquityPriceUpdateDlg::addPricePair(const MyMoneySecurityPair& pair, bool dontCheckExistance) { MyMoneyFile* file = MyMoneyFile::instance(); QString symbol = QString("%1 > %2").arg(pair.first, pair.second); QString id = QString("%1 %2").arg(pair.first, pair.second); // Check that the pair does not already exist if (lvEquityList->findItems(id, Qt::MatchExactly, ID_COL).empty()) { const MyMoneyPrice &pr = file->price(pair.first, pair.second); if (pr.source() != "KMyMoney") { bool keep = true; if ((pair.first == file->baseCurrency().id()) || (pair.second == file->baseCurrency().id())) { const QString& foreignCurrency = file->foreignCurrency(pair.first, pair.second); // check that the foreign currency is still in use QList<MyMoneyAccount>::const_iterator it_a; QList<MyMoneyAccount> list; file->accountList(list); for (it_a = list.constBegin(); !dontCheckExistance && it_a != list.constEnd(); ++it_a) { // if it's an account denominated in the foreign currency // keep it if (((*it_a).currencyId() == foreignCurrency) && !(*it_a).isClosed()) break; // if it's an investment traded in the foreign currency // keep it if ((*it_a).isInvest() && !(*it_a).isClosed()) { MyMoneySecurity sec = file->security((*it_a).currencyId()); if (sec.tradingCurrency() == foreignCurrency) break; } } // if it is in use, it_a is not equal to list.end() if (it_a == list.constEnd() && !dontCheckExistance) keep = false; } if (keep) { QTreeWidgetItem* item = new QTreeWidgetItem(); item->setText(SYMBOL_COL, symbol); item->setText(NAME_COL, i18n("%1 units in %2", pair.first, pair.second)); if (pr.isValid()) { item->setText(PRICE_COL, pr.rate(pair.second).formatMoney(file->currency(pair.second).tradingSymbol(), KMyMoneyGlobalSettings::pricePrecision())); item->setText(DATE_COL, pr.date().toString(Qt::ISODate)); } item->setText(ID_COL, id); item->setText(SOURCE_COL, "Yahoo Currency"); // This string value should not be localized lvEquityList->invisibleRootItem()->addChild(item); } } } }
void KForecastView::updateBudget(QTreeWidgetItem *item) { MyMoneySecurity currency; MyMoneyMoney tAmountMM; MyMoneyForecast forecast = item->data(0, ForecastRole).value<MyMoneyForecast>(); MyMoneyFile* file = MyMoneyFile::instance(); int it_c = 1; // iterator for the columns of the listview QDate forecastDate = forecast.forecastStartDate(); MyMoneyAccount account = item->data(0, AccountRole).value<MyMoneyAccount>(); if (account.isInvest()) { MyMoneySecurity underSecurity = file->security(account.currencyId()); currency = file->security(underSecurity.tradingCurrency()); } else { currency = file->security(account.currencyId()); } //iterate columns for (; forecastDate <= forecast.forecastEndDate(); forecastDate = forecastDate.addMonths(1), ++it_c) { MyMoneyMoney amountMM; amountMM = forecast.forecastBalance(account, forecastDate); if (account.accountType() == MyMoneyAccount::Expense) amountMM = -amountMM; tAmountMM += amountMM; setAmount(item, it_c, amountMM); setValue(item, it_c, amountMM, forecastDate); showAmount(item, it_c, amountMM, currency); } //set total column setAmount(item, it_c, tAmountMM); setValue(item, it_c, tAmountMM, forecast.forecastEndDate()); showAmount(item, it_c, tAmountMM, currency); }
void KForecastView::updateDetailed(QTreeWidgetItem *item) { QString amount; QString vAmount; MyMoneyMoney vAmountMM; MyMoneyFile* file = MyMoneyFile::instance(); MyMoneyAccount account = item->data(0, AccountRole).value<MyMoneyAccount>(); MyMoneySecurity currency; if (account.isInvest()) { MyMoneySecurity underSecurity = file->security(account.currencyId()); currency = file->security(underSecurity.tradingCurrency()); } else { currency = file->security(account.currencyId()); } int it_c = 1; // iterator for the columns of the listview MyMoneyForecast forecast = item->data(0, ForecastRole).value<MyMoneyForecast>(); for (QDate forecastDate = QDate::currentDate(); forecastDate <= forecast.forecastEndDate(); ++it_c, forecastDate = forecastDate.addDays(1)) { MyMoneyMoney amountMM = forecast.forecastBalance(account, forecastDate); //calculate the balance in base currency for the total row setAmount(item, it_c, amountMM); setValue(item, it_c, amountMM, forecastDate); showAmount(item, it_c, amountMM, currency); } //calculate and add variation per cycle vAmountMM = forecast.accountTotalVariation(account); setAmount(item, it_c, vAmountMM); setValue(item, it_c, vAmountMM, forecast.forecastEndDate()); showAmount(item, it_c, vAmountMM, currency); }
QList<MyMoneyPrice> KForecastView::getAccountPrices(const MyMoneyAccount& acc) { MyMoneyFile* file = MyMoneyFile::instance(); QList<MyMoneyPrice> prices; MyMoneySecurity security = file->baseCurrency(); try { if (acc.isInvest()) { security = file->security(acc.currencyId()); if (security.tradingCurrency() != file->baseCurrency().id()) { MyMoneySecurity sec = file->security(security.tradingCurrency()); prices += file->price(sec.id(), file->baseCurrency().id()); } } else if (acc.currencyId() != file->baseCurrency().id()) { if (acc.currencyId() != file->baseCurrency().id()) { security = file->security(acc.currencyId()); prices += file->price(acc.currencyId(), file->baseCurrency().id()); } } } catch (const MyMoneyException &e) { qDebug() << Q_FUNC_INFO << " caught exception while adding " << acc.name() << "[" << acc.id() << "]: " << e.what(); } return prices; }
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); } } } } }
MyMoneyMoney ReportAccount::foreignCurrencyPrice(const QString foreignCurrency, const QDate& date, bool exactDate) const { DEBUG_ENTER(Q_FUNC_INFO); MyMoneyMoney result(1, 1); MyMoneyFile* file = MyMoneyFile::instance(); MyMoneySecurity security = file->security(foreignCurrency); //check whether it is a currency or a commodity. In the latter case case, get the trading currency QString tradingCurrency; if (security.isCurrency()) { tradingCurrency = foreignCurrency; } else { tradingCurrency = security.tradingCurrency(); } //It makes no sense to get the price if both currencies are the same if (currency().id() != tradingCurrency) { const MyMoneyPrice &price = file->price(currency().id(), tradingCurrency, date, exactDate); if (price.isValid()) { result = price.rate(tradingCurrency); DEBUG_OUTPUT(QString("Converting deep %1 to currency %2, price on %3 is %4") .arg(file->currency(currency().id()).name()) .arg(file->currency(foreignCurrency).name()) .arg(date.toString()) .arg(result.toDouble())); } else { DEBUG_OUTPUT(QString("No price to convert deep %1 to currency %2 on %3") .arg(file->currency(currency().id()).name()) .arg(file->currency(foreignCurrency).name()) .arg(date.toString())); } } return result; }
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::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 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 CsvUtil::createAccount(MyMoneyAccount& newAccount, MyMoneyAccount& parentAccount, MyMoneyAccount& brokerageAccount, MyMoneyMoney openingBal) { MyMoneyFile* file = MyMoneyFile::instance(); // make sure we have a currency. If none is assigned, we assume base currency if (newAccount.currencyId().isEmpty()) newAccount.setCurrencyId(file->baseCurrency().id()); MyMoneyFileTransaction ft; try { int pos; // check for ':' in the name and use it as separator for a hierarchy while ((pos = newAccount.name().indexOf(MyMoneyFile::AccountSeperator)) != -1) { QString part = newAccount.name().left(pos); QString remainder = newAccount.name().mid(pos + 1); const MyMoneyAccount& existingAccount = file->subAccountByName(parentAccount, part); if (existingAccount.id().isEmpty()) { newAccount.setName(part); file->addAccount(newAccount, parentAccount); parentAccount = newAccount; } else { parentAccount = existingAccount; } newAccount.setParentAccountId(QString()); // make sure, there's no parent newAccount.clearId(); // and no id set for adding newAccount.removeAccountIds(); // and no sub-account ids newAccount.setName(remainder); } const MyMoneySecurity& sec = file->security(newAccount.currencyId()); // Check the opening balance if (openingBal.isPositive() && newAccount.accountGroup() == MyMoneyAccount::Liability) { QString message = i18n("This account is a liability and if the " "opening balance represents money owed, then it should be negative. " "Negate the amount?\n\n" "Please click Yes to change the opening balance to %1,\n" "Please click No to leave the amount as %2,\n" "Please click Cancel to abort the account creation." , MyMoneyUtils::formatMoney(-openingBal, newAccount, sec) , MyMoneyUtils::formatMoney(openingBal, newAccount, sec)); int ans = KMessageBox::questionYesNoCancel(0, message); if (ans == KMessageBox::Yes) { openingBal = -openingBal; } else if (ans == KMessageBox::Cancel) return; } file->addAccount(newAccount, parentAccount); if (newAccount.accountType() == MyMoneyAccount::Investment && !brokerageAccount.name().isEmpty()) { file->addAccount(brokerageAccount, parentAccount); // set a link from the investment account to the brokerage account file->modifyAccount(newAccount); file->createOpeningBalanceTransaction(brokerageAccount, openingBal); } else file->createOpeningBalanceTransaction(newAccount, openingBal); ft.commit(); } catch (const MyMoneyException &e) { KMessageBox::information(0, i18n("Unable to add account: %1", e.what())); } }
KEquityPriceUpdateDlg::KEquityPriceUpdateDlg(QWidget *parent, const QString& securityId) : KEquityPriceUpdateDlgDecl(parent), m_fUpdateAll(false) { QStringList headerList; headerList << i18n("Symbol") << i18nc("Equity name", "Name") << i18n("Price") << i18n("Date"); lvEquityList->header()->setSortIndicator(0, Qt::AscendingOrder); lvEquityList->setColumnWidth(NAME_COL, 125); // This is a "get it up and running" hack. Will replace this in the future. headerList << i18nc("Internal identifier", "ID") << i18nc("Online quote source", "Source"); lvEquityList->setColumnWidth(ID_COL, 0); lvEquityList->setHeaderLabels(headerList); lvEquityList->setSelectionMode(QAbstractItemView::MultiSelection); lvEquityList->setAllColumnsShowFocus(true); btnUpdateAll->setEnabled(false); btnOK->setGuiItem(KStandardGuiItem::ok()); btnCancel->setGuiItem(KStandardGuiItem::cancel()); MyMoneyFile* file = MyMoneyFile::instance(); // // Add each price pair that we know about // // send in securityId == "XXX YYY" to get a single-shot update for XXX to YYY. // for consistency reasons, this accepts the same delimiters as WebPriceQuote::launch() QRegExp splitrx("([0-9a-z\\.]+)[^a-z0-9]+([0-9a-z\\.]+)", Qt::CaseInsensitive); MyMoneySecurityPair currencyIds; if (splitrx.indexIn(securityId) != -1) { currencyIds = MyMoneySecurityPair(splitrx.cap(1).toUtf8(), splitrx.cap(2).toUtf8()); } MyMoneyPriceList prices = file->priceList(); for (MyMoneyPriceList::ConstIterator it_price = prices.constBegin(); it_price != prices.constEnd(); ++it_price) { const MyMoneySecurityPair& pair = it_price.key(); if (file->security(pair.first).isCurrency() && (securityId.isEmpty() || (pair == currencyIds))) { const MyMoneyPriceEntries& entries = (*it_price); if (entries.count() > 0 && entries.begin().key() <= QDate::currentDate()) { addPricePair(pair); btnUpdateAll->setEnabled(true); } } } // // Add each investment // QList<MyMoneySecurity> securities = file->securityList(); for (QList<MyMoneySecurity>::const_iterator it = securities.constBegin(); it != securities.constEnd(); ++it) { if (!(*it).isCurrency() && (securityId.isEmpty() || ((*it).id() == securityId)) && !(*it).value("kmm-online-source").isEmpty() ) { addInvestment(*it); btnUpdateAll->setEnabled(true); } } // if list is empty, add the request price pair if (lvEquityList->invisibleRootItem()->childCount() == 0) { addPricePair(currencyIds, true); } connect(btnOK, SIGNAL(clicked()), this, SLOT(accept())); connect(btnCancel, SIGNAL(clicked()), this, SLOT(reject())); connect(btnUpdateSelected, SIGNAL(clicked()), this, SLOT(slotUpdateSelectedClicked())); connect(btnUpdateAll, SIGNAL(clicked()), this, SLOT(slotUpdateAllClicked())); connect(&m_webQuote, SIGNAL(quote(QString,QString,QDate,double)), this, SLOT(slotReceivedQuote(QString,QString,QDate,double))); connect(&m_webQuote, SIGNAL(failed(QString,QString)), this, SLOT(slotQuoteFailed(QString,QString))); connect(&m_webQuote, SIGNAL(status(QString)), this, SLOT(logStatusMessage(QString))); connect(&m_webQuote, SIGNAL(error(QString)), this, SLOT(logErrorMessage(QString))); connect(lvEquityList, SIGNAL(itemSelectionChanged()), this, SLOT(slotUpdateSelection())); // Not implemented yet. btnConfigure->hide(); //connect(btnConfigure, SIGNAL(clicked()), this, SLOT(slotConfigureClicked())); if (!securityId.isEmpty()) { btnUpdateSelected->hide(); btnUpdateAll->hide(); // delete layout1; QTimer::singleShot(100, this, SLOT(slotUpdateAllClicked())); } // Hide OK button until we have received the first update btnOK->setEnabled(false); slotUpdateSelection(); // previous versions of this dialog allowed to store a "Don't ask again" switch. // Since we don't support it anymore, we just get rid of it KSharedConfigPtr config = KGlobal::config(); KConfigGroup grp = config->group("Notification Messages"); grp.deleteEntry("KEquityPriceUpdateDlg::slotQuoteFailed::Price Update Failed"); }
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(); }