Skip to content

Commit

Permalink
[ADD] : add panes for categories and operations
Browse files Browse the repository at this point in the history
  • Loading branch information
aiekick committed Jun 17, 2024
1 parent b8363fa commit aa06d8f
Show file tree
Hide file tree
Showing 15 changed files with 528 additions and 9 deletions.
4 changes: 4 additions & 0 deletions src/Frontend/MainFrontend.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ limitations under the License.
#include <Panes/ConsolePane.h>
#include <Panes/AccountPane.h>
#include <Panes/EntitiesPane.h>
#include <Panes/CategoriesPane.h>
#include <Panes/OperationsPane.h>

#include <Systems/SettingsDialog.h>

Expand Down Expand Up @@ -79,6 +81,8 @@ bool MainFrontend::init() {
LayoutManager::Instance()->AddPane(StatsPane::Instance(), "Statistics", "", "CENTRAL", 0.0f, false, false);
LayoutManager::Instance()->AddPane(BudgetPane::Instance(), "Budget", "", "CENTRAL", 0.0f, false, false);
LayoutManager::Instance()->AddPane(EntitiesPane::Instance(), "Entities", "", "CENTRAL", 0.0f, false, false);
LayoutManager::Instance()->AddPane(CategoriesPane::Instance(), "Categories", "", "CENTRAL", 0.0f, false, false);
LayoutManager::Instance()->AddPane(OperationsPane::Instance(), "Operations", "", "CENTRAL", 0.0f, false, false);
LayoutManager::Instance()->AddPane(ConsolePane::Instance(), "Console", "", "BOTTOM", 0.25f, false, false);

// InitPanes is done in m_InitPanes, because a specific order is needed
Expand Down
73 changes: 73 additions & 0 deletions src/Frontend/Tables/CategoriesTable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <Frontend/Tables/CategoriesTable.h>
#include <Models/DataBase.h>

CategoriesTable::CategoriesTable() : ADataTable("CategoriesTable", 5) {
}

CategoriesTable::~CategoriesTable() {
}

bool CategoriesTable::load() {
ADataTable::load();
m_updateCategories();
return true;
}

void CategoriesTable::unload() {
ADataTable::unload();
}

bool CategoriesTable::drawMenu() {
if (ADataTable::drawMenu()) {
m_updateCategories();
return true;
}
return false;
}

double CategoriesTable::m_getAmount(const size_t& vIdx) {
return m_Categories.at(vIdx).amount;
}

void CategoriesTable::m_drawContent(const size_t& vIdx, const double& vMaxAmount) {
const auto& e = m_Categories.at(vIdx);
ImGui::TableNextColumn();
ImGui::Text("%s", e.name.c_str());
m_drawColumnDebit(e.debit);
m_drawColumnCredit(e.credit);
m_drawColumnAmount(e.amount);
m_drawColumnBars(e.amount, vMaxAmount);
}

size_t CategoriesTable::m_getItemsCount() {
return m_Categories.size();
}

void CategoriesTable::m_setupColumns() {
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Debit", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Credit", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Amount", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Bars", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableHeadersRow();
}

void CategoriesTable::m_updateCategories() {
const auto account_id = m_getAccountID();
if (account_id > 0) {
m_Categories.clear();
DataBase::Instance()->GetCategoriesStats( //
account_id,
[this](const CategoryName& vCategoryName,
const TransactionDebit& vTransactionDebit,
const TransactionCredit& vTransactionCredit) { //
Category e;
e.name = vCategoryName;
e.debit = vTransactionDebit;
e.credit = vTransactionCredit;
e.amount = vTransactionDebit + vTransactionCredit;
m_Categories.push_back(e);
});
}
}
25 changes: 25 additions & 0 deletions src/Frontend/Tables/CategoriesTable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <Frontend/Tables/abstract/ADataTable.h>

class CategoriesTable : public ADataTable {
private:
std::vector<Category> m_Categories;

public:
CategoriesTable();
~CategoriesTable();

bool load();
void unload();
bool drawMenu();

protected:
double m_getAmount(const size_t& vIdx) final;
void m_drawContent(const size_t& vIdx, const double& vMaxAmount) final;
size_t m_getItemsCount() final;
void m_setupColumns() final;

private:
void m_updateCategories();
};
73 changes: 73 additions & 0 deletions src/Frontend/Tables/OperationsTable.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
#include <Frontend/Tables/OperationsTable.h>
#include <Models/DataBase.h>

OperationsTable::OperationsTable() : ADataTable("OperationsTable", 5) {
}

OperationsTable::~OperationsTable() {
}

bool OperationsTable::load() {
ADataTable::load();
m_updateOperations();
return true;
}

void OperationsTable::unload() {
ADataTable::unload();
}

bool OperationsTable::drawMenu() {
if (ADataTable::drawMenu()) {
m_updateOperations();
return true;
}
return false;
}

double OperationsTable::m_getAmount(const size_t& vIdx) {
return m_Operations.at(vIdx).amount;
}

void OperationsTable::m_drawContent(const size_t& vIdx, const double& vMaxAmount) {
const auto& e = m_Operations.at(vIdx);
ImGui::TableNextColumn();
ImGui::Text("%s", e.name.c_str());
m_drawColumnDebit(e.debit);
m_drawColumnCredit(e.credit);
m_drawColumnAmount(e.amount);
m_drawColumnBars(e.amount, vMaxAmount);
}

size_t OperationsTable::m_getItemsCount() {
return m_Operations.size();
}

void OperationsTable::m_setupColumns() {
ImGui::TableSetupScrollFreeze(0, 1);
ImGui::TableSetupColumn("Name", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Debit", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Credit", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Amount", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableSetupColumn("Bars", ImGuiTableColumnFlags_WidthFixed);
ImGui::TableHeadersRow();
}

void OperationsTable::m_updateOperations() {
const auto account_id = m_getAccountID();
if (account_id > 0) {
m_Operations.clear();
DataBase::Instance()->GetOperationsStats( //
account_id,
[this](const OperationName& vOperationName,
const TransactionDebit& vTransactionDebit,
const TransactionCredit& vTransactionCredit) { //
Operation e;
e.name = vOperationName;
e.debit = vTransactionDebit;
e.credit = vTransactionCredit;
e.amount = vTransactionDebit + vTransactionCredit;
m_Operations.push_back(e);
});
}
}
25 changes: 25 additions & 0 deletions src/Frontend/Tables/OperationsTable.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#pragma once

#include <Frontend/Tables/abstract/ADataTable.h>

class OperationsTable : public ADataTable {
private:
std::vector<Operation> m_Operations;

public:
OperationsTable();
~OperationsTable();

bool load();
void unload();
bool drawMenu();

protected:
double m_getAmount(const size_t& vIdx) final;
void m_drawContent(const size_t& vIdx, const double& vMaxAmount) final;
size_t m_getItemsCount() final;
void m_setupColumns() final;

private:
void m_updateOperations();
};
4 changes: 2 additions & 2 deletions src/Headers/CashMeBuild.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#pragma once

#define CashMe_Prefix "CashMe"
#define CashMe_BuildNumber 615
#define CashMe_BuildNumber 618
#define CashMe_MinorNumber 0
#define CashMe_MajorNumber 0
#define CashMe_BuildId "0.0.615"
#define CashMe_BuildId "0.0.618"
92 changes: 92 additions & 0 deletions src/Models/DataBase.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -379,6 +379,52 @@ void DataBase::GetCategories(std::function<void(const CategoryName&)> vCallback)
}
}

void DataBase::GetCategoriesStats( //
const RowID& vAccountID,
std::function<void( //
const CategoryName&,
const TransactionDebit&,
const TransactionCredit&)> vCallback) {
// no interest to call that without a callback for retrieve datas
assert(vCallback);
const auto& select_query = ct::toStr(
u8R"(
SELECT
categories.name AS new_category,
ROUND(SUM(CASE WHEN transactions.amount < 0 THEN amount ELSE 0 END), 2) AS new_debit,
ROUND(SUM(CASE WHEN transactions.amount > 0 THEN amount ELSE 0 END), 2) AS new_credit
FROM
transactions
LEFT JOIN categories ON transactions.category_id = categories.id
WHERE
account_id = %u
GROUP BY
new_category
ORDER BY
new_category;
)",
vAccountID);
if (m_OpenDB()) {
sqlite3_stmt* stmt = nullptr;
int res = debug_sqlite3_prepare_v2(__FUNCTION__, m_SqliteDB, select_query.c_str(), (int)select_query.size(), &stmt, nullptr);
if (res != SQLITE_OK) {
LogVarError("%s %s", "Fail get categories with reason", sqlite3_errmsg(m_SqliteDB));
} else {
while (res == SQLITE_OK || res == SQLITE_ROW) {
res = sqlite3_step(stmt);
if (res == SQLITE_OK || res == SQLITE_ROW) {
auto name = (const char*)sqlite3_column_text(stmt, 0);
auto debit = (TransactionDebit)sqlite3_column_double(stmt, 1);
auto credit = (TransactionCredit)sqlite3_column_double(stmt, 2);
vCallback(name != nullptr ? name : "", debit, credit);
}
}
}
sqlite3_finalize(stmt);
m_CloseDB();
}
}

void DataBase::UpdateCategory(const RowID& vRowID, const CategoryName& vCategoryName) {
auto insert_query = ct::toStr(u8R"(UPDATE categories SET name = "%s" WHERE id = %u;)", vCategoryName.c_str(), vRowID);
if (debug_sqlite3_exec(__FUNCTION__, m_SqliteDB, insert_query.c_str(), nullptr, nullptr, &m_LastErrorMsg) != SQLITE_OK) {
Expand Down Expand Up @@ -449,6 +495,52 @@ void DataBase::GetOperations(std::function<void(const OperationName&)> vCallback
}
}

void DataBase::GetOperationsStats( //
const RowID& vAccountID,
std::function<void( //
const OperationName&,
const TransactionDebit&,
const TransactionCredit&)> vCallback) {
// no interest to call that without a callback for retrieve datas
assert(vCallback);
const auto& select_query = ct::toStr(
u8R"(
SELECT
operations.name AS new_operation,
ROUND(SUM(CASE WHEN transactions.amount < 0 THEN amount ELSE 0 END), 2) AS new_debit,
ROUND(SUM(CASE WHEN transactions.amount > 0 THEN amount ELSE 0 END), 2) AS new_credit
FROM
transactions
LEFT JOIN operations ON transactions.operation_id = operations.id
WHERE
account_id = %u
GROUP BY
new_operation
ORDER BY
new_operation;
)",
vAccountID);
if (m_OpenDB()) {
sqlite3_stmt* stmt = nullptr;
int res = debug_sqlite3_prepare_v2(__FUNCTION__, m_SqliteDB, select_query.c_str(), (int)select_query.size(), &stmt, nullptr);
if (res != SQLITE_OK) {
LogVarError("%s %s", "Fail get operations with reason", sqlite3_errmsg(m_SqliteDB));
} else {
while (res == SQLITE_OK || res == SQLITE_ROW) {
res = sqlite3_step(stmt);
if (res == SQLITE_OK || res == SQLITE_ROW) {
auto name = (const char*)sqlite3_column_text(stmt, 0);
auto debit = (TransactionDebit)sqlite3_column_double(stmt, 1);
auto credit = (TransactionCredit)sqlite3_column_double(stmt, 2);
vCallback(name != nullptr ? name : "", debit, credit);
}
}
}
sqlite3_finalize(stmt);
m_CloseDB();
}
}

void DataBase::UpdateOperation(const RowID& vRowID, const OperationName& vOperationName) {
auto insert_query = ct::toStr(u8R"(UPDATE operations SET name = "%s" WHERE id = %u;)", vOperationName.c_str(), vRowID);
if (debug_sqlite3_exec(__FUNCTION__, m_SqliteDB, insert_query.c_str(), nullptr, nullptr, &m_LastErrorMsg) != SQLITE_OK) {
Expand Down
12 changes: 12 additions & 0 deletions src/Models/DataBase.h
Original file line number Diff line number Diff line change
Expand Up @@ -64,12 +64,24 @@ class DataBase {
void AddCategory(const CategoryName& vCategoryName);
bool GetCategory(const CategoryName& vUserName, RowID& vOutRowID);
void GetCategories(std::function<void(const CategoryName&)> vCallback);
void GetCategoriesStats( //
const RowID& vAccountID,
std::function<void( //
const CategoryName&,
const TransactionDebit&,
const TransactionCredit&)> vCallback);
void UpdateCategory(const RowID& vRowID, const CategoryName& vCategoryName);
void DeleteCategories();

void AddOperation(const OperationName& vOperationName);
bool GetOperation(const OperationName& vUserName, RowID& vOutRowID);
void GetOperations(std::function<void(const OperationName&)> vCallback);
void GetOperationsStats( //
const RowID& vAccountID,
std::function<void( //
const OperationName&,
const TransactionDebit&,
const TransactionCredit&)> vCallback);
void UpdateOperation(const RowID& vRowID, const OperationName& vOperationName);
void DeleteOperations();

Expand Down
Loading

0 comments on commit aa06d8f

Please sign in to comment.