diff --git a/init.sql b/init.sql index 20dd6ef..0eef6cb 100644 --- a/init.sql +++ b/init.sql @@ -2,7 +2,7 @@ CREATE TABLE kisscount(db_version VARCHAR(20)); CREATE TABLE user (id INTEGER PRIMARY KEY, name VARCHAR(255), password VARCHAR(255)); CREATE TABLE account(id INTEGER PRIMARY KEY, user REFERENCES user(id), name VARCHAR(255), number VARCHAR(255), shared CHAR(1), default_account CHAR(1)); CREATE TABLE account_amount(id INTEGER PRIMARY KEY, account REFERENCES account(id), year INTEGER, month INTEGER, amount FLOAT); -CREATE TABLE operation(id INTEGER PRIMARY KEY, parent REFERENCES operation(id), user REFERENCES user(id), account REFERENCES account(id), year INTEGER, month INTEGER, day INTEGER, amount FLOAT, description VARCHAR(255), category REFERENCES category(id), fix_cost CHAR(1), checked CHAR(1), formula VARCHAR(255)); +CREATE TABLE operation(id INTEGER PRIMARY KEY, parent REFERENCES operation(id), user REFERENCES user(id), account REFERENCES account(id), year INTEGER, month INTEGER, day INTEGER, amount FLOAT, description VARCHAR(255), category REFERENCES category(id), fix_cost CHAR(1), checked CHAR(1), formula VARCHAR(255), transfert REFERENCES operation(id)); CREATE TABLE category(id INTEGER PRIMARY KEY, user REFERENCES user(id), parent REFERENCES category(id), name VARCHAR(255), color VARCHAR(255), font VARCHAR(255)); CREATE TABLE preference(id INTEGER PRIMARY KEY, user REFERENCES user(id), name VARCHAR(255), value VARCHAR(255)); INSERT INTO kisscount ("db_version") VALUES ("1"); diff --git a/src/controller/KissCount.cpp b/src/controller/KissCount.cpp index 157b530..c383553 100644 --- a/src/controller/KissCount.cpp +++ b/src/controller/KissCount.cpp @@ -93,16 +93,33 @@ double KissCount::GetAccountAmount(const wxString& id, int month, int year) void KissCount::UpdateOperation(Operation& op) { + // Unlink + op.transfert = wxT(""); + _user->LinkOrUnlinkOperation(op); + _db->UpdateOperation(op); + + // Link + _user->LinkOrUnlinkOperation(op); } wxString KissCount::AddOperation(Operation& op) { - return _db->AddOperation(_user, op); + wxString ret = _db->AddOperation(_user, op); + + if (op.transfert.Length()) + _user->LinkOrUnlinkOperation(op); + + return ret; } void KissCount::DeleteOperation(Operation& op) { + if (op.transfert.Length()) + { + op.transfert = wxT(""); + _user->LinkOrUnlinkOperation(op); + } _db->DeleteOperation(op); } diff --git a/src/model/Database.cpp b/src/model/Database.cpp index 8798049..ae0d8ed 100644 --- a/src/model/Database.cpp +++ b/src/model/Database.cpp @@ -316,6 +316,7 @@ void Database::LoadYear(User* user, int year) op.category = set.GetAsString(wxT("category")); op.fix_cost = set.GetBool(wxT("fix_cost")); op.checked = set.GetBool(wxT("checked")); + op.transfert = set.GetAsString(wxT("transfert")); op.formula = set.GetAsString(wxT("formula")); (*user->_operations[op.year])[op.month].push_back(op); } @@ -349,9 +350,93 @@ double Database::GetAccountAmount(const wxString& id, int month, int year) return res; } +bool Database::GetOperation(const wxString& id, Operation* op) +{ + wxSQLite3ResultSet set; + wxString req; + + req = wxT("SELECT * FROM operation WHERE id='") + id + wxT("'"); + + EXECUTE_SQL_QUERY(req, set, false); + + if (!set.NextRow()) return false; + + op->id = set.GetAsString(wxT("id")); + op->parent = set.GetAsString(wxT("parent")); + op->account = set.GetAsString(wxT("account")); + op->day = set.GetInt(wxT("day")); + op->month = set.GetInt(wxT("month")); + op->year = set.GetInt(wxT("year")); + op->amount = set.GetDouble(wxT("amount")); + op->description = set.GetAsString(wxT("description")); + op->category = set.GetAsString(wxT("category")); + op->fix_cost = set.GetBool(wxT("fix_cost")); + op->checked = set.GetBool(wxT("checked")); + op->transfert = set.GetAsString(wxT("transfert")); + op->formula = set.GetAsString(wxT("formula")); + + return true; +} + +void Database::LinkOrUnlinkOperation(Operation& op) +{ + Operation linked; + wxString req; + wxSQLite3ResultSet set; + + if (op.transfert.Length()) + { + // No one or not linked + if (!GetOperation(op.transfert, &linked) || op.description != linked.description || op.amount != -linked.amount) + { + req = wxT("UPDATE operation SET transfert='' where id='") + op.id + wxT("'") ; + EXECUTE_SQL_UPDATE(req, ); + return; + } + } + // Not Linked + else + { + req = wxT("SELECT id FROM operation WHERE transfert='") + op.id + wxT("'"); + + EXECUTE_SQL_QUERY(req, set, ); + + if (set.NextRow()) + { + req = wxT("UPDATE operation SET transfert='' where id='") + set.GetAsString(wxT("id")) + wxT("'") ; + EXECUTE_SQL_UPDATE(req, ); + } + + req = wxT("SELECT id FROM operation WHERE description='") + op.description + wxT("'"); + req += wxT(" AND month='") + wxString::Format(wxT("%d"), op.month) + wxT("'"); + req += wxT(" AND year='") + wxString::Format(wxT("%d"), op.year) + wxT("'"); + req += wxT(" AND amount='") + DoubleToString(-op.amount) + wxT("'"); + req += wxT(" AND transfert=''"); + + EXECUTE_SQL_QUERY(req, set, ); + + // Don't need to link + if (!set.NextRow()) return ; + + // Link + linked.id = set.GetAsString(wxT("id")); + + op.transfert = linked.id; + + req = wxT("UPDATE operation SET transfert='") + linked.id + wxT("' where id='") + op.id + wxT("'") ; + EXECUTE_SQL_UPDATE(req, ); + + req = wxT("UPDATE operation SET transfert='") + op.id + wxT("' where id='") + linked.id + wxT("'") ; + EXECUTE_SQL_UPDATE(req, ); + } +} + void Database::UpdateOperation(Operation& op) { wxString req; + + LinkOrUnlinkOperation(op); + req = wxT("UPDATE operation SET ") ; req += wxT("parent='") + op.parent + wxT("'"); req += wxT(", account='") + op.account + wxT("'"); @@ -365,10 +450,13 @@ void Database::UpdateOperation(Operation& op) req += wxT(", checked='1'"); else req += wxT(", checked='0'"); + req += wxT(", transfert='") + op.transfert + wxT("'"); req += wxT(", formula='") + op.formula + wxT("'"); req += wxT(" WHERE id='") + op.id + wxT("'"); EXECUTE_SQL_UPDATE(req, ); + + LinkOrUnlinkOperation(op); } wxString Database::AddOperation(User* user, Operation& op) @@ -376,7 +464,7 @@ wxString Database::AddOperation(User* user, Operation& op) wxString req, res; wxSQLite3ResultSet set; - req = wxT("INSERT INTO operation ('user', 'parent', 'account', 'year', 'month', 'day', 'amount', 'description', 'category', 'fix_cost', 'formula') VALUES ('") ; + req = wxT("INSERT INTO operation ('user', 'parent', 'account', 'year', 'month', 'day', 'amount', 'description', 'category', 'fix_cost', 'formula', 'transfert') VALUES ('") ; req += user->_id + wxT("'"); req += wxT(", '") + op.parent + wxT("'"); req += wxT(", '") + op.account + wxT("'"); @@ -391,6 +479,7 @@ wxString Database::AddOperation(User* user, Operation& op) else req += wxT(", '0'") ; req += wxT(", '") + op.formula + wxT("'"); + req += wxT(", '") + op.transfert + wxT("'"); req += wxT(")"); EXECUTE_SQL_UPDATE(req, wxT("0")); @@ -410,6 +499,7 @@ wxString Database::AddOperation(User* user, Operation& op) else req += wxT(" AND fix_cost='0'") ; req += wxT(" AND formula='") + op.formula + wxT("'"); + req += wxT(" AND transfert='") + op.transfert + wxT("'"); req += wxT("ORDER BY id DESC") ; EXECUTE_SQL_QUERY(req , set, wxT("0")); @@ -421,6 +511,10 @@ wxString Database::AddOperation(User* user, Operation& op) set.Finalize(); + op.id = res; + + LinkOrUnlinkOperation(op); + return res; } @@ -430,6 +524,8 @@ void Database::DeleteOperation(Operation& op) req = wxT("DELETE FROM operation WHERE id='") + op.id + wxT("'"); EXECUTE_SQL_UPDATE(req, ); + + LinkOrUnlinkOperation(op); } void Database::DeleteOperations(User* user, int month, int year) @@ -939,7 +1035,7 @@ std::vector* Database::Search(User* user, wxString* description, wxDa if (description) { - req += wxT("description LIKE '%") + *description + wxT("%'"); + req += wxT("description='") + *description + wxT("'"); firstCond = true; } @@ -1099,6 +1195,7 @@ void Database::GetStats(User* user, const wxString& monthFrom, const wxString& y 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 amount < 0"); + req += wxT(" AND transfert=''"); EXECUTE_SQL_QUERY(req, set, ); diff --git a/src/model/Database.h b/src/model/Database.h index dc4dade..fdd2747 100644 --- a/src/model/Database.h +++ b/src/model/Database.h @@ -77,11 +77,13 @@ class Database std::map* categories); void KillMe(User* user); + bool GetOperation(const wxString& id, Operation* op); private: wxSQLite3Database _db; void CreateDatabase(); wxString HashPassword(const wxString& password); + void LinkOrUnlinkOperation(Operation& op); }; #endif diff --git a/src/model/Operation.h b/src/model/Operation.h index 79d5c52..ddf49af 100644 --- a/src/model/Operation.h +++ b/src/model/Operation.h @@ -33,6 +33,7 @@ class Operation { bool fix_cost; wxString account; bool checked; + wxString transfert; wxString formula; } ; diff --git a/src/model/User.cpp b/src/model/User.cpp index 5bee18a..eca4ac9 100644 --- a/src/model/User.cpp +++ b/src/model/User.cpp @@ -117,3 +117,34 @@ wxLanguage User::GetLanguage() return (wxLanguage)val; } + +void User::LinkOrUnlinkOperation(Operation& op) +{ + std::vector::iterator it; + + // Not Linked + if (!op.transfert.Length()) + { + for (it = (*_operations[op.year])[op.month].begin(); it != (*_operations[op.year])[op.month].end(); it++) + { + if (it->id != op.id && it->transfert == op.id) + { + it->transfert = wxT(""); + return; + } + } + } + // Linked + else + { + for (it = (*_operations[op.year])[op.month].begin(); it != (*_operations[op.year])[op.month].end(); it++) + { + if (it->id != op.id && it->id == op.transfert) + { + it->transfert = op.id; + return; + } + } + op.transfert = wxT(""); + } +} diff --git a/src/model/User.h b/src/model/User.h index 75b64f3..135c3e9 100644 --- a/src/model/User.h +++ b/src/model/User.h @@ -51,6 +51,7 @@ class User int GetAccountsNumber(); int GetOperationsNumber(int month, int year); wxLanguage GetLanguage(); + void LinkOrUnlinkOperation(Operation& op); }; #endif diff --git a/src/view/AccountPanel.cpp b/src/view/AccountPanel.cpp index d7263ed..a3ff9c4 100644 --- a/src/view/AccountPanel.cpp +++ b/src/view/AccountPanel.cpp @@ -458,6 +458,7 @@ void AccountPanel::UpdateStats() for (it=_curOperations->begin(); it!=_curOperations->end(); it++) { + if (it->transfert.Length()) continue; if (it->amount > 0) { if (day >= it->day) @@ -591,7 +592,7 @@ void AccountPanel::OnOperationModified(wxGridEvent& event) _grid->GetCellValue(event.GetRow(), CATEGORY) == wxT("") && _grid->GetCellValue(event.GetRow(), ACCOUNT) == wxT("")) { - if (_kiss->SearchPreviousOperation(&op_tmp, new_op.description, _curMonth-3, _curYear)) + if (_kiss->SearchPreviousOperation(&op_tmp, new_op.description, _curMonth, _curYear)) { new_op.category = op_tmp.category; new_op.account = op_tmp.account; @@ -627,7 +628,6 @@ void AccountPanel::OnOperationModified(wxGridEvent& event) } } - // Penser au fix implosif // Modify a fix operation if (row < _fixCosts) { @@ -646,16 +646,22 @@ void AccountPanel::OnOperationModified(wxGridEvent& event) new_op.id = cur_op.id; new_op.fix_cost = true; + new_op.transfert = cur_op.transfert; + if (cur_op.day != new_op.day) { need_insertion = true; _grid->DeleteRows(event.GetRow(), 1); _curOperations->erase(_curOperations->begin()+row); _fixCosts--; + _kiss->UpdateOperation(new_op); } else - (*_curOperations)[row] = new_op; - _kiss->UpdateOperation(new_op); + { + _kiss->UpdateOperation(new_op); + (*_curOperations)[row] = new_op; + } + fix_op = true; } // Add a fixCost @@ -683,6 +689,7 @@ void AccountPanel::OnOperationModified(wxGridEvent& event) cur_op = (*_curOperations)[row] ; new_op.id = cur_op.id; new_op.fix_cost = false; + new_op.transfert = cur_op.transfert; if (col == DELETE) { @@ -699,10 +706,13 @@ void AccountPanel::OnOperationModified(wxGridEvent& event) need_insertion = true; _grid->DeleteRows(event.GetRow(), 1); _curOperations->erase(_curOperations->begin()+row); + _kiss->UpdateOperation(new_op); } else - (*_curOperations)[row] = new_op; - _kiss->UpdateOperation(new_op); + { + _kiss->UpdateOperation(new_op); + (*_curOperations)[row] = new_op; + } } // Add an operation else @@ -733,6 +743,7 @@ void AccountPanel::OnOperationModified(wxGridEvent& event) { if ((*_curOperations)[i].day > new_op.day) break; + } else { diff --git a/src/view/SearchPanel.cpp b/src/view/SearchPanel.cpp index 041057c..75d3a7e 100644 --- a/src/view/SearchPanel.cpp +++ b/src/view/SearchPanel.cpp @@ -356,6 +356,7 @@ void SearchPanel::OnOperationModified(wxGridEvent& event) cur_op = (*_operations)[row] ; new_op.id = cur_op.id; new_op.fix_cost = false; + new_op.transfert = cur_op.transfert; if (col == DELETE) { diff --git a/tools/package.sh b/tools/package.sh index 47423ea..1368036 100755 --- a/tools/package.sh +++ b/tools/package.sh @@ -1,7 +1,7 @@ #!/bin/bash DATE=`date +%d.%m.%Y` -DIR="build_$DATE" +DIR="KissCount_build_$DATE" FILE="$DIR.tar.bz2" rm -f $FILE