Skip to content

Commit

Permalink
V2022.1.1
Browse files Browse the repository at this point in the history
- Added support for repeating transactions
- ID will now automatically increment starting from 1
- Added action color to buttons
  • Loading branch information
nlogozzo committed Jan 12, 2022
1 parent a8f4d08 commit af9d632
Show file tree
Hide file tree
Showing 11 changed files with 182 additions and 19 deletions.
2 changes: 1 addition & 1 deletion UpdateConfig.json
Original file line number Diff line number Diff line change
@@ -1 +1 @@
{"LatestVersion":"2022.1.0","Changelog":"- Initial Release","LinkToExe":"https://github.com/nlogozzo/NickvisionMoney/releases/download/2022.1.0/NickvisionMoney"}
{"LatestVersion":"2022.1.1","Changelog":"- Added support for repeating transactions\n- ID will now automatically increment starting from 1\n- Added action color to buttons","LinkToExe":"https://github.com/nlogozzo/NickvisionMoney/releases/download/2022.1.1/NickvisionMoney"}
1 change: 1 addition & 0 deletions controls/headerbar.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ namespace NickvisionMoney::Controls
m_lblDeleteTransaction.set_label("Are you sure you want to delete this transaction?");
m_lblDeleteTransaction.set_margin(4);
m_btnDTDelete.set_label("Delete");
m_btnDTDelete.get_style_context()->add_class("destructive-action");
m_btnDTCancel.set_label("Cancel");
m_btnDTCancel.signal_clicked().connect(sigc::mem_fun(m_popDeleteTransaction, &Gtk::Popover::popdown));
m_boxDTBtns.set_homogeneous(true);
Expand Down
86 changes: 79 additions & 7 deletions models/account.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,92 @@
#include <sstream>
#include <iomanip>
#include <cmath>
#include <gtkmm.h>

namespace NickvisionMoney::Models
{
Account::Account(const std::string& path) : m_path(path), m_db(m_path, SQLite::OPEN_READWRITE | SQLite::OPEN_CREATE)
{
m_db.exec("CREATE TABLE IF NOT EXISTS transactions (id INTEGER PRIMARY KEY, date TEXT, description TEXT, type INTEGER, amount REAL)");
m_db.exec("CREATE TABLE IF NOT EXISTS transactions (id INTEGER PRIMARY KEY, date TEXT, description TEXT, type INTEGER, repeat INTEGER, amount REAL)");
SQLite::Statement qryGetAll(m_db, "SELECT * FROM transactions");
while(qryGetAll.executeStep())
{
Transaction transaction(qryGetAll.getColumn(0).getInt());
transaction.setDate(qryGetAll.getColumn(1).getString());
transaction.setDescription(qryGetAll.getColumn(2).getString());
transaction.setType(static_cast<TransactionType>(qryGetAll.getColumn(3).getInt()));
transaction.setAmount(qryGetAll.getColumn(4).getDouble());
transaction.setRepeatInterval(static_cast<RepeatInterval>(qryGetAll.getColumn(4).getInt()));
transaction.setAmount(qryGetAll.getColumn(5).getDouble());
m_transactions.insert({ transaction.getID(), transaction });
}
//==Repeat Needed Transactions==//
size_t i = 0;
size_t startingSize = m_transactions.size();
std::map<unsigned int, Transaction>::iterator it = m_transactions.begin();
while(i != startingSize)
{
Transaction transaction = it->second;
if(transaction.getRepeatInterval() != RepeatInterval::Never)
{
bool repeatNeeeded = false;
if(transaction.getRepeatInterval() == RepeatInterval::Daily)
{
if(Glib::DateTime::create_now_utc().compare(Glib::DateTime::create_from_iso8601(transaction.getDate()).add_days(1)) != -1)
{
repeatNeeeded = true;
}
}
else if(transaction.getRepeatInterval() == RepeatInterval::Weekly)
{
if(Glib::DateTime::create_now_utc().compare(Glib::DateTime::create_from_iso8601(transaction.getDate()).add_days(7)) != -1)
{
repeatNeeeded = true;
}
}
else if(transaction.getRepeatInterval() == RepeatInterval::Monthly)
{
if(Glib::DateTime::create_now_utc().compare(Glib::DateTime::create_from_iso8601(transaction.getDate()).add_months(1)) != -1)
{
repeatNeeeded = true;
}
}
else if(transaction.getRepeatInterval() == RepeatInterval::Quarterly)
{
if(Glib::DateTime::create_now_utc().compare(Glib::DateTime::create_from_iso8601(transaction.getDate()).add_months(4)) != -1)
{
repeatNeeeded = true;
}
}
else if(transaction.getRepeatInterval() == RepeatInterval::Yearly)
{
if(Glib::DateTime::create_now_utc().compare(Glib::DateTime::create_from_iso8601(transaction.getDate()).add_years(1)) != -1)
{
repeatNeeeded = true;
}
}
else
{
if(Glib::DateTime::create_now_utc().compare(Glib::DateTime::create_from_iso8601(transaction.getDate()).add_years(2)) != -1)
{
repeatNeeeded = true;
}
}
if(repeatNeeeded)
{
Transaction newTransaction(getNextID());
newTransaction.setDate(Glib::DateTime::create_now_utc().format_iso8601());
newTransaction.setDescription(transaction.getDescription());
newTransaction.setType(transaction.getType());
newTransaction.setRepeatInterval(transaction.getRepeatInterval());
newTransaction.setAmount(transaction.getAmount());
addTransaction(newTransaction);
transaction.setRepeatInterval(RepeatInterval::Never);
updateTransaction(transaction);
}
}
i++;
it++;
}
}

const std::string& Account::getPath() const
Expand All @@ -43,7 +113,7 @@ namespace NickvisionMoney::Models
}
}

int Account::getNextID() const
unsigned int Account::getNextID() const
{
if(m_transactions.empty())
{
Expand All @@ -57,12 +127,13 @@ namespace NickvisionMoney::Models

bool Account::addTransaction(const Transaction& transaction)
{
SQLite::Statement qryInsert(m_db, "INSERT INTO transactions (id, date, description, type, amount) VALUES (?, ?, ?, ?, ?)");
SQLite::Statement qryInsert(m_db, "INSERT INTO transactions (id, date, description, type, repeat, amount) VALUES (?, ?, ?, ?, ?, ?)");
qryInsert.bind(1, transaction.getID());
qryInsert.bind(2, transaction.getDate());
qryInsert.bind(3, transaction.getDescription());
qryInsert.bind(4, static_cast<int>(transaction.getType()));
qryInsert.bind(5, transaction.getAmount());
qryInsert.bind(5, static_cast<int>(transaction.getRepeatInterval()));
qryInsert.bind(6, transaction.getAmount());
if(qryInsert.exec() > 0)
{
m_transactions.insert({ transaction.getID(), transaction });
Expand All @@ -73,11 +144,12 @@ namespace NickvisionMoney::Models

bool Account::updateTransaction(const Transaction& transaction)
{
SQLite::Statement qryUpdate(m_db, "UPDATE transactions SET date = ?, description = ?, type = ?, amount = ? WHERE id = " + std::to_string(transaction.getID()));
SQLite::Statement qryUpdate(m_db, "UPDATE transactions SET date = ?, description = ?, type = ?, repeat = ?, amount = ? WHERE id = " + std::to_string(transaction.getID()));
qryUpdate.bind(1, transaction.getDate());
qryUpdate.bind(2, transaction.getDescription());
qryUpdate.bind(3, static_cast<int>(transaction.getType()));
qryUpdate.bind(4, transaction.getAmount());
qryUpdate.bind(4, static_cast<int>(transaction.getRepeatInterval()));
qryUpdate.bind(5, transaction.getAmount());
if(qryUpdate.exec() > 0)
{
m_transactions[transaction.getID()] = transaction;
Expand Down
2 changes: 1 addition & 1 deletion models/account.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace NickvisionMoney::Models
const std::string& getPath() const;
const std::map<unsigned int, Transaction>& getTransactions() const;
std::optional<Transaction> getTransactionByID(unsigned int id) const;
int getNextID() const;
unsigned int getNextID() const;
bool addTransaction(const Transaction& transaction);
bool updateTransaction(const Transaction& transaction);
bool deleteTransaction(unsigned int id);
Expand Down
6 changes: 6 additions & 0 deletions models/datatransactionscolumns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ namespace NickvisionMoney::Models
add(m_colDate);
add(m_colDescription);
add(m_colType);
add(m_colRepeatInterval);
add(m_colAmount);
}

Expand All @@ -31,6 +32,11 @@ namespace NickvisionMoney::Models
return m_colType;
}

const Gtk::TreeModelColumn<std::string>& DataTransactionsColumns::getColRepeatInterval() const
{
return m_colRepeatInterval;
}

const Gtk::TreeModelColumn<std::string>& DataTransactionsColumns::getColAmount() const
{
return m_colAmount;
Expand Down
2 changes: 2 additions & 0 deletions models/datatransactionscolumns.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,15 @@ namespace NickvisionMoney::Models
const Gtk::TreeModelColumn<std::string>& getColDate() const;
const Gtk::TreeModelColumn<std::string>& getColDescription() const;
const Gtk::TreeModelColumn<std::string>& getColType() const;
const Gtk::TreeModelColumn<std::string>& getColRepeatInterval() const;
const Gtk::TreeModelColumn<std::string>& getColAmount() const;

private:
Gtk::TreeModelColumn<unsigned int> m_colID;
Gtk::TreeModelColumn<std::string> m_colDate;
Gtk::TreeModelColumn<std::string> m_colDescription;
Gtk::TreeModelColumn<std::string> m_colType;
Gtk::TreeModelColumn<std::string> m_colRepeatInterval;
Gtk::TreeModelColumn<std::string> m_colAmount;
};
}
Expand Down
44 changes: 43 additions & 1 deletion models/transaction.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

namespace NickvisionMoney::Models
{
Transaction::Transaction(unsigned int id) : m_id(id), m_date("1-1-2000"), m_description(""), m_type(TransactionType::Income), m_amount(0.00)
Transaction::Transaction(unsigned int id) : m_id(id), m_date("1-1-2000"), m_description(""), m_type(TransactionType::Income), m_repeatInterval(RepeatInterval::Never), m_amount(0.00)
{

}
Expand Down Expand Up @@ -57,6 +57,48 @@ namespace NickvisionMoney::Models
m_type = type;
}

RepeatInterval Transaction::getRepeatInterval() const
{
return m_repeatInterval;
}

std::string Transaction::getRepeatIntervalAsString() const
{
if(m_repeatInterval == RepeatInterval::Never)
{
return "Never";
}
else if(m_repeatInterval == RepeatInterval::Daily)
{
return "Daily";
}
else if(m_repeatInterval == RepeatInterval::Weekly)
{
return "Weekly";
}
else if(m_repeatInterval == RepeatInterval::Monthly)
{
return "Monthly";
}
else if(m_repeatInterval == RepeatInterval::Quarterly)
{
return "Quarterly";
}
else if(m_repeatInterval == RepeatInterval::Yearly)
{
return "Yearly";
}
else
{
return "Biyearly";
}
}

void Transaction::setRepeatInterval(RepeatInterval repeatInterval)
{
m_repeatInterval = repeatInterval;
}

double Transaction::getAmount() const
{
return m_amount;
Expand Down
15 changes: 15 additions & 0 deletions models/transaction.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,17 @@ namespace NickvisionMoney::Models
Expense
};

enum class RepeatInterval
{
Never,
Daily,
Weekly,
Monthly,
Quarterly,
Yearly,
Biyearly
};

class Transaction
{
public:
Expand All @@ -23,6 +34,9 @@ namespace NickvisionMoney::Models
TransactionType getType() const;
std::string getTypeAsString() const;
void setType(TransactionType type);
RepeatInterval getRepeatInterval() const;
std::string getRepeatIntervalAsString() const;
void setRepeatInterval(RepeatInterval repeatInterval);
double getAmount() const;
std::string getAmountAsString() const;
void setAmount(double amount);
Expand All @@ -36,6 +50,7 @@ namespace NickvisionMoney::Models
std::string m_date;
std::string m_description;
TransactionType m_type;
RepeatInterval m_repeatInterval;
double m_amount;
};
}
Expand Down
20 changes: 13 additions & 7 deletions views/mainwindow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace NickvisionMoney::Views
using namespace NickvisionMoney::Models;
using namespace NickvisionMoney::Controls;

MainWindow::MainWindow() : m_opened(false), m_updater("https://raw.githubusercontent.com/nlogozzo/NickvisionMoney/main/UpdateConfig.json", { "2022.1.0" }), m_account(std::nullopt)
MainWindow::MainWindow() : m_opened(false), m_updater("https://raw.githubusercontent.com/nlogozzo/NickvisionMoney/main/UpdateConfig.json", { "2022.1.1" }), m_account(std::nullopt)
{
//==Settings==//
set_default_size(800, 600);
Expand Down Expand Up @@ -78,6 +78,7 @@ namespace NickvisionMoney::Views
m_dataTransactions.append_column("Date", m_dataTransactionsColumns.getColDate());
m_dataTransactions.append_column("Description", m_dataTransactionsColumns.getColDescription());
m_dataTransactions.append_column("Type", m_dataTransactionsColumns.getColType());
m_dataTransactions.append_column("Repeat Interval", m_dataTransactionsColumns.getColRepeatInterval());
m_dataTransactions.append_column("Amount", m_dataTransactionsColumns.getColAmount());
m_dataTransactions.set_model(m_dataTransactionsModel);
m_dataTransactions.get_selection()->set_mode(Gtk::SelectionMode::SINGLE);
Expand Down Expand Up @@ -144,7 +145,8 @@ namespace NickvisionMoney::Views
{
Gtk::FileChooserDialog* folderDialog = new Gtk::FileChooserDialog(*this, "Save New Account File", Gtk::FileChooserDialog::Action::SAVE, true);
folderDialog->set_modal(true);
folderDialog->add_button("_Save", Gtk::ResponseType::OK);
Gtk::Button* btnSave = folderDialog->add_button("_Save", Gtk::ResponseType::OK);
btnSave->get_style_context()->add_class("suggested-action");
folderDialog->add_button("_Cancel", Gtk::ResponseType::CANCEL);
std::shared_ptr<Gtk::FileFilter> accountFileFilter = Gtk::FileFilter::create();
accountFileFilter->set_name("Nickvision Money Account");
Expand Down Expand Up @@ -180,7 +182,8 @@ namespace NickvisionMoney::Views
{
Gtk::FileChooserDialog* folderDialog = new Gtk::FileChooserDialog(*this, "Open Account File", Gtk::FileChooserDialog::Action::OPEN, true);
folderDialog->set_modal(true);
folderDialog->add_button("_Open", Gtk::ResponseType::OK);
Gtk::Button* btnOpen = folderDialog->add_button("_Open", Gtk::ResponseType::OK);
btnOpen->get_style_context()->add_class("suggested-action");
folderDialog->add_button("_Cancel", Gtk::ResponseType::CANCEL);
std::shared_ptr<Gtk::FileFilter> accountFileFilter = Gtk::FileFilter::create();
accountFileFilter->set_name("Nickvision Money Account");
Expand Down Expand Up @@ -264,7 +267,8 @@ namespace NickvisionMoney::Views
{
Gtk::FileChooserDialog* folderDialog = new Gtk::FileChooserDialog(*this, "Save Backup Account File", Gtk::FileChooserDialog::Action::SAVE, true);
folderDialog->set_modal(true);
folderDialog->add_button("_Save", Gtk::ResponseType::OK);
Gtk::Button* btnSave = folderDialog->add_button("_Save", Gtk::ResponseType::OK);
btnSave->get_style_context()->add_class("suggested-action");
folderDialog->add_button("_Cancel", Gtk::ResponseType::CANCEL);
std::shared_ptr<Gtk::FileFilter> accountFileFilter = Gtk::FileFilter::create();
accountFileFilter->set_name("Nickvision Money Backup");
Expand Down Expand Up @@ -295,7 +299,8 @@ namespace NickvisionMoney::Views
{
Gtk::FileChooserDialog* folderDialog = new Gtk::FileChooserDialog(*this, "Open Backup File", Gtk::FileChooserDialog::Action::OPEN, true);
folderDialog->set_modal(true);
folderDialog->add_button("_Open", Gtk::ResponseType::OK);
Gtk::Button* btnOpen = folderDialog->add_button("_Open", Gtk::ResponseType::OK);
btnOpen->get_style_context()->add_class("suggested-action");
folderDialog->add_button("_Cancel", Gtk::ResponseType::CANCEL);
std::shared_ptr<Gtk::FileFilter> accountFileFilter = Gtk::FileFilter::create();
accountFileFilter->set_name("Nickvision Money Backup");
Expand Down Expand Up @@ -385,7 +390,7 @@ namespace NickvisionMoney::Views
void MainWindow::changelog(const Glib::VariantBase& args)
{
Gtk::MessageDialog* changelogDialog = new Gtk::MessageDialog(*this, "What's New?", false, Gtk::MessageType::INFO, Gtk::ButtonsType::OK, true);
changelogDialog->set_secondary_text("\n- Initial Release");
changelogDialog->set_secondary_text("\n- Added support for repeating transactions\n- ID will now automatically increment starting from 1\n- Added action color to buttons");
changelogDialog->signal_response().connect(sigc::bind([](int response, Gtk::MessageDialog* dialog)
{
delete dialog;
Expand All @@ -400,7 +405,7 @@ namespace NickvisionMoney::Views
aboutDialog->set_modal(true);
aboutDialog->set_hide_on_close(true);
aboutDialog->set_program_name("Nickvision Money");
aboutDialog->set_version("2022.1.0");
aboutDialog->set_version("2022.1.1");
aboutDialog->set_comments("A personal finance manager.");
aboutDialog->set_copyright("(C) Nickvision 2021-2022");
aboutDialog->set_license_type(Gtk::License::GPL_3_0);
Expand Down Expand Up @@ -434,6 +439,7 @@ namespace NickvisionMoney::Views
row[m_dataTransactionsColumns.getColDate()] = pair.second.getDate().substr(0, 10);
row[m_dataTransactionsColumns.getColDescription()] = pair.second.getDescription();
row[m_dataTransactionsColumns.getColType()] = pair.second.getTypeAsString();
row[m_dataTransactionsColumns.getColRepeatInterval()] = pair.second.getRepeatIntervalAsString();
row[m_dataTransactionsColumns.getColAmount()] = pair.second.getAmountAsString();
}
}
Expand Down
Loading

0 comments on commit af9d632

Please sign in to comment.