From 84aa1fb42bbe4141fb31bc46387ce02a2edd138c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Gr=C3=A9gory=20Soutad=C3=A9?= Date: Fri, 19 Nov 2010 19:58:02 +0100 Subject: [PATCH] Add inner month statistics --- src/controller/KissCount.cpp | 11 +++ src/controller/KissCount.h | 4 + src/model/Database.cpp | 142 ++++++++++++++++++++++++++--------- src/model/Database.h | 4 + src/view/StatsPanel.cpp | 126 +++++++++++++++++++++---------- tools/package.sh | 3 +- 6 files changed, 212 insertions(+), 78 deletions(-) diff --git a/src/controller/KissCount.cpp b/src/controller/KissCount.cpp index a68eaaa..d1892a6 100644 --- a/src/controller/KissCount.cpp +++ b/src/controller/KissCount.cpp @@ -445,6 +445,17 @@ void KissCount::GetStats(int monthFrom, int yearFrom, int monthTo, int yearTo, _db->GetStats(_user, monthF, yearF, monthT, yearT, accountAmounts, categories); } +void KissCount::GetMonthStats(int month, int year, int nbDays, + std::map >* operations, + std::map* categories) +{ + wxString monthS = wxString::Format(wxT("%d"), month); + wxString yearS = wxString::Format(wxT("%d"), year); + + _db->GetMonthStats(_user, monthS, yearS, nbDays, operations, categories); +} + + std::map* KissCount::GetNotChecked(int month, int year) { return _db->GetNotChecked(_user, month, year); diff --git a/src/controller/KissCount.h b/src/controller/KissCount.h index 1e14609..13cda18 100644 --- a/src/controller/KissCount.h +++ b/src/controller/KissCount.h @@ -90,6 +90,10 @@ public: std::map > >* accountAmounts, std::map* categories); + void GetMonthStats(int month, int year, int nbDays, + std::map >* operations, + std::map* categories); + std::map* GetNotChecked(int month, int year); static wxFont ExtractFont(wxString strFont); diff --git a/src/model/Database.cpp b/src/model/Database.cpp index 757faf8..85b2a51 100644 --- a/src/model/Database.cpp +++ b/src/model/Database.cpp @@ -1406,65 +1406,135 @@ void Database::GetStats(User* user, const wxString& monthFrom, const wxString& y std::vector::iterator accountIt; std::vector::iterator categoryIt; + if (!user->_accounts.empty()) + { + if (accountAmounts) + { + for (accountIt = user->_accounts.begin(); accountIt != user->_accounts.end(); accountIt++) + { + req = wxT("SELECT month, year, amount FROM account_amount WHERE account ='") + accountIt->id + wxT("'"); + req += wxT(" AND (year > '") + yearFrom + wxT("' OR (year == '") + yearFrom + wxT("' AND month >= '") + monthFrom + wxT("'))"); + req += wxT(" AND (year < '") + yearTo + wxT("' OR (year == '") + yearTo + wxT("' AND month <= '") + monthTo + wxT("'))"); + + EXECUTE_SQL_QUERY(req, set, ); + + while (set.NextRow()) + { + (*accountAmounts)[accountIt->id][set.GetInt(wxT("year"))][set.GetInt(wxT("month"))] = set.GetInt(wxT("amount")); + } + set.Finalize(); + } + } + + if (categories) + { + for (categoryIt = user->_categories.begin(); categoryIt != user->_categories.end(); categoryIt++) + { + req = wxT("SELECT SUM(amount) as amount FROM operation AS o1 WHERE category='") + categoryIt->id + wxT("'"); + accountIt = user->_accounts.begin(); + req += wxT(" AND (account IN('") + accountIt->id; + accountIt++; + for (;accountIt != user->_accounts.end(); accountIt++) + { + req += wxT("', '") + accountIt->id ; + } + req += wxT("')"); + req += wxT(" OR user='") + user->_id + wxT("')"); + + req += wxT(" AND (year > '") + yearFrom + wxT("' OR (year == '") + yearFrom + wxT("' AND month >= '") + monthFrom + wxT("'))"); + req += wxT(" AND (year < '") + yearTo + wxT("' OR (year == '") + yearTo + wxT("' AND month <= '") + monthTo + wxT("'))"); + req += wxT(" AND meta='0'"); + + req2 = req + wxT(" AND (transfert='' OR transfert IS NULL)"); + req2 += wxT(" AND amount < 0"); + + EXECUTE_SQL_QUERY(req2, set, ); + + if (set.NextRow()) + { + (*categories)[categoryIt->id] = -set.GetDouble(wxT("amount")); + } + set.Finalize(); + + // Transfert on blocked accounts must be computed + req2 = req + wxT(" AND transfert != ''"); + req2 = req + wxT(" AND (SELECT blocked FROM account WHERE id=o1.account)"); + req2 += wxT(" AND amount > 0"); + + EXECUTE_SQL_QUERY(req2, set, ); + + if (set.NextRow()) + { + (*categories)[categoryIt->id] += set.GetDouble(wxT("amount")); + } + set.Finalize(); + } + } + } +} + +void Database::GetMonthStats(User* user, const wxString& month, const wxString& year, int nbDays, + std::map >* operations, + std::map* categories) +{ + wxSQLite3ResultSet set; + wxString req; + std::vector::iterator accountIt; + int previous_amount, previous_day, cur_day; + if (!user->_accounts.empty()) { for (accountIt = user->_accounts.begin(); accountIt != user->_accounts.end(); accountIt++) { - req = wxT("SELECT month, year, amount FROM account_amount WHERE account ='") + accountIt->id + wxT("'"); - req += wxT(" AND (year > '") + yearFrom + wxT("' OR (year == '") + yearFrom + wxT("' AND month >= '") + monthFrom + wxT("'))"); - req += wxT(" AND (year < '") + yearTo + wxT("' OR (year == '") + yearTo + wxT("' AND month <= '") + monthTo + wxT("'))"); + req = wxT("SELECT amount FROM account_amount WHERE account ='") + accountIt->id + wxT("'"); + req += wxT(" AND year = '") + year + wxT("'"); + req += wxT(" AND month = '") + month + wxT("'"); EXECUTE_SQL_QUERY(req, set, ); while (set.NextRow()) { - (*accountAmounts)[accountIt->id][set.GetInt(wxT("year"))][set.GetInt(wxT("month"))] = set.GetInt(wxT("amount")); + (*operations)[accountIt->id].clear(); + + previous_amount = set.GetInt(wxT("amount")); } set.Finalize(); - } - for (categoryIt = user->_categories.begin(); categoryIt != user->_categories.end(); categoryIt++) - { - req = wxT("SELECT SUM(amount) as amount FROM operation AS o1 WHERE category='") + categoryIt->id + wxT("'"); - accountIt = user->_accounts.begin(); - req += wxT(" AND (account IN('") + accountIt->id; - accountIt++; - for (;accountIt != user->_accounts.end(); accountIt++) - { - req += wxT("', '") + accountIt->id ; - } - req += wxT("')"); - req += wxT(" OR user='") + user->_id + wxT("')"); - - req += wxT(" AND (year > '") + yearFrom + wxT("' OR (year == '") + yearFrom + wxT("' AND month >= '") + monthFrom + wxT("'))"); - req += wxT(" AND (year < '") + yearTo + wxT("' OR (year == '") + yearTo + wxT("' AND month <= '") + monthTo + wxT("'))"); + req = wxT("SELECT day, amount FROM operation WHERE"); + req += wxT(" account = '") + accountIt->id + wxT("'"); + req += wxT(" AND year = '") + year + wxT("'"); + req += wxT(" AND month = '") + month + wxT("'"); req += wxT(" AND meta='0'"); - req2 = req + wxT(" AND (transfert='' OR transfert IS NULL)"); - req2 += wxT(" AND amount < 0"); + req += wxT(" ORDER BY day ASC"); - EXECUTE_SQL_QUERY(req2, set, ); + EXECUTE_SQL_QUERY(req, set, ); - if (set.NextRow()) + cur_day = previous_day = -1; + while (set.NextRow()) { - (*categories)[categoryIt->id] = -set.GetDouble(wxT("amount")); + cur_day = set.GetInt(wxT("day")); + while (cur_day != previous_day) + { + (*operations)[accountIt->id].push_back(previous_amount); + previous_day++; + } + + previous_amount += set.GetDouble(wxT("amount")); + (*operations)[accountIt->id][cur_day] = previous_amount; } - set.Finalize(); + set.Finalize(); - // Transfert on blocked accounts must be computed - req2 = req + wxT(" AND transfert != ''"); - req2 = req + wxT(" AND (SELECT blocked FROM account WHERE id=o1.account)"); - req2 += wxT(" AND amount > 0"); - - EXECUTE_SQL_QUERY(req2, set, ); - - if (set.NextRow()) + while (cur_day < nbDays) { - (*categories)[categoryIt->id] += set.GetDouble(wxT("amount")); + (*operations)[accountIt->id].push_back(previous_amount); + cur_day++; } - set.Finalize(); } } + + // Fill categories + GetStats(user, month, year, month, year, NULL, categories) ; } std::map* Database::GetNotChecked(User* user, int month, int year) diff --git a/src/model/Database.h b/src/model/Database.h index 10c175c..0780da6 100644 --- a/src/model/Database.h +++ b/src/model/Database.h @@ -89,6 +89,10 @@ public: const wxString& yearTo, std::map > >* accountAmounts, std::map* categories); + void GetMonthStats(User* user, const wxString& month, const wxString& year, int nbDays, + std::map >* operations, + std::map* categories); + void KillMe(User* user); bool GetOperation(const wxString& id, Operation* op); std::map getSharedAccountOwners(const wxString& account); diff --git a/src/view/StatsPanel.cpp b/src/view/StatsPanel.cpp index af89dfe..62ca913 100644 --- a/src/view/StatsPanel.cpp +++ b/src/view/StatsPanel.cpp @@ -151,14 +151,17 @@ void StatsPanel::UpdateStats(int monthFrom, int yearFrom, int monthTo, int yearT { std::map > > accountAmounts; std::map categories; + std::map > operations; + std::map >::iterator accountIdIt2; std::map::iterator categoriesIt; std::map > >::iterator accountIdIt; std::map >::iterator accountYearIt; double total; - int size, i, a, b, percents, account; + int size, i, a, b, percents, account, nbDays; double *amounts; wxString value; User* user = _kiss->GetUser(); + wxDateTime date; if (_chart) { @@ -167,58 +170,100 @@ void StatsPanel::UpdateStats(int monthFrom, int yearFrom, int monthTo, int yearT delete _chart; } - _kiss->GetStats(monthFrom, yearFrom, monthTo, yearTo, &accountAmounts, &categories); - // first step: create plot _plot = new XYPlot(); // create dataset XYSimpleDataset *dataset = new XYSimpleDataset(); - // Line on 0 all over the years - size = ((yearTo - yearFrom) + 1) * 12; - amounts = new double[size*2]; - for (a=0; a<(size/12); a++) + if (monthFrom == monthTo && yearFrom == yearTo) { - for(b=0; b<12; b++) - { - amounts[a*12*2+b*2+0] = a*12+b; - amounts[a*12*2+b*2+1] = 0; - } - } + nbDays = date.GetLastMonthDay((wxDateTime::Month)monthFrom, yearFrom).GetDay(); - dataset->AddSerie((double *) amounts, size); - delete[] amounts; - - for (account = 0, i = 0, accountIdIt = accountAmounts.begin(); accountIdIt != accountAmounts.end(); - accountIdIt++, i++, account++) - { - if (!((wxCheckListBox*)_account)->IsChecked(account)) - { - i-- ; - continue; + _kiss->GetMonthStats(monthFrom, yearFrom, nbDays, &operations, &categories); + + // Line on 0 all over the years + amounts = new double[nbDays*2]; + for (a=0; afirst].size(); - amounts = new double[size*12*2]; - size = 0; - for(a = 0, accountYearIt = accountAmounts[accountIdIt->first].begin(); - accountYearIt != accountAmounts[accountIdIt->first].end(); - accountYearIt++, a++) + dataset->AddSerie((double *) amounts, nbDays); + delete[] amounts; + + for (account = 0, i = 0, accountIdIt2 = operations.begin(); accountIdIt2 != operations.end(); + accountIdIt2++, i++, account++) { - for(b = 0; b<12; b++) + if (!((wxCheckListBox*)_account)->IsChecked(account)) + { + i-- ; + continue; + } + + amounts = new double[nbDays*2]; + size = 0; + for (a=0; afirst][accountYearIt->first].count(b)) - continue; - amounts[size*2+0] = a*12+b; - amounts[size*2+1] = accountAmounts[accountIdIt->first][accountYearIt->first][b]; - size++; + amounts[a*2+0] = a; + amounts[a*2+1] = operations[accountIdIt2->first][a]; + } + dataset->AddSerie((double *) amounts, nbDays); + // set serie names to be displayed on legend + dataset->SetSerieName(i+1, user->GetAccountName(accountIdIt2->first)); + delete[] amounts; + } + } + else + { + _kiss->GetStats(monthFrom, yearFrom, monthTo, yearTo, &accountAmounts, &categories); + + // Line on 0 all over the years + size = ((yearTo - yearFrom) + 1) * 12; + amounts = new double[size*2]; + for (a=0; a<(size/12); a++) + { + for(b=0; b<12; b++) + { + amounts[a*12*2+b*2+0] = a*12+b; + amounts[a*12*2+b*2+1] = 0; } } - dataset->AddSerie((double *) amounts, size); - // set serie names to be displayed on legend - dataset->SetSerieName(i+1, user->GetAccountName(accountIdIt->first)); - delete[] amounts; + + dataset->AddSerie((double *) amounts, size); + delete[] amounts; + + for (account = 0, i = 0, accountIdIt = accountAmounts.begin(); accountIdIt != accountAmounts.end(); + accountIdIt++, i++, account++) + { + if (!((wxCheckListBox*)_account)->IsChecked(account)) + { + i-- ; + continue; + } + + size = accountAmounts[accountIdIt->first].size(); + amounts = new double[size*12*2]; + size = 0; + for(a = 0, accountYearIt = accountAmounts[accountIdIt->first].begin(); + accountYearIt != accountAmounts[accountIdIt->first].end(); + accountYearIt++, a++) + { + for(b = 0; b<12; b++) + { + if (!accountAmounts[accountIdIt->first][accountYearIt->first].count(b)) + continue; + amounts[size*2+0] = a*12+b; + amounts[size*2+1] = accountAmounts[accountIdIt->first][accountYearIt->first][b]; + size++; + } + } + dataset->AddSerie((double *) amounts, size); + // set serie names to be displayed on legend + dataset->SetSerieName(i+1, user->GetAccountName(accountIdIt->first)); + delete[] amounts; + } } // create line renderer and set it to dataset @@ -296,9 +341,8 @@ void StatsPanel::OnRangeChange(wxCommandEvent& event) _yearTo->GetStringSelection().ToLong(&yearTo); if (yearTo > yearFrom || - (yearFrom == yearTo && monthFrom >= monthTo)) + (yearFrom == yearTo && monthFrom > monthTo)) { - std::cout << monthFrom << " " << monthTo << " " << _yearFrom->GetStringSelection().mb_str() << " " << yearFrom << " " << yearTo << "\n" ; wxMessageBox(_("Invalide date range"), _("KissCount"), wxICON_ERROR | wxOK); return; } diff --git a/tools/package.sh b/tools/package.sh index f0c2c0e..668e2cf 100755 --- a/tools/package.sh +++ b/tools/package.sh @@ -1,7 +1,8 @@ #!/bin/bash DATE=`date +%d.%m.%Y` -DIR="KissCount_build_$DATE" +ARCH=`uname -m` +DIR="KissCount_build_${DATE}_${ARCH}" FILE="$DIR.tar.bz2" rm -f $FILE