diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml new file mode 100644 index 0000000..a55e7a1 --- /dev/null +++ b/.idea/codeStyles/codeStyleConfig.xml @@ -0,0 +1,5 @@ + + + + \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 7ec662b..b59602c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -3,4 +3,10 @@ project(budget) set(CMAKE_CXX_STANDARD 20) -add_executable(budget src/main.cpp src/money/account.cpp src/money/account.h) \ No newline at end of file +add_executable(${PROJECT_NAME} src/main.cpp src/main.h + src/money/account.cpp src/money/account.h + src/money/transaction.cpp src/money/transaction.h + src/money/recept.cpp src/money/recept.h + src/data/data.tpp src/data/data.h + src/data/accountData.cpp src/data/accountData.h + src/money/earning.cpp src/money/earning.h) \ No newline at end of file diff --git a/src/data/accountData.cpp b/src/data/accountData.cpp new file mode 100644 index 0000000..4610414 --- /dev/null +++ b/src/data/accountData.cpp @@ -0,0 +1,83 @@ +// +// Created by quentin on 8/4/22. +// + +#include "accountData.h" +#include +#include + +AccountData::AccountData(const std::string &file) : Data(file) { + account = AccountData::createObject(); +} + +Account AccountData::createObject() { + if (isJsonCorrect()) { + bool withdrawable = document["withdrawable"].GetBool(); + std::string name = document["name"].GetString(); + + std::list transactions; + for (auto &domTransaction : document["transactions"].GetArray()) { + Receipt receipt(domTransaction["receipt"]["file"].GetString()); + int value = domTransaction["value"].GetInt(); + + transactions.emplace_back(value, receipt); + } + + std::list earnings; + for (auto &domEarning : document["earnings"].GetArray()) { + earnings.emplace_back(domEarning["value"].GetInt()); + } + + return Account(transactions, earnings, withdrawable, name); + } + + std::string strAnswer; + bool answer; + while (true) { + std::cout << "Account " + getFilePath() + " not found, would you like to remove it from the database? (Y/n): "; + std::cin >> strAnswer; + std::transform(strAnswer.begin(), strAnswer.end(), strAnswer.begin(), ::toupper); + if (strAnswer == "Y" || strAnswer == "YES") { + answer = true; + break; + } + if (strAnswer == "N" || strAnswer == "NO") { + answer = false; + break; + } + std::cout << "Sorry, answer " + strAnswer + " not understood." << std::endl; + } + + return Account(); +} + +bool AccountData::isJsonCorrect() { + if (document.IsObject() && + document.HasMember("withdrawable") && document["withdrawable"].IsBool() && + document.HasMember("name") && document["name"].IsString() && + document.HasMember("transactions") && document["transactions"].IsArray() && + document.HasMember("earnings") && document["earnings"].IsArray()) { + for (auto &domTransaction : document["transactions"].GetArray()) { + if (!(domTransaction.IsObject() && + domTransaction.HasMember("receipt") && domTransaction["receipt"].IsObject() && + domTransaction["receipt"].HasMember("file") && domTransaction["receipt"]["file"].IsString() && + domTransaction.HasMember("value") && domTransaction["value"].IsInt())) { + return false; + } + } + for (auto &domEarning : document["earnings"].GetArray()) { + if (!(domEarning.IsObject() && + domEarning.HasMember("value") && domEarning["value"].IsInt())) { + return false; + } + } + + return true; + } + + return false; +} + +Account *AccountData::getAccount() { + return &account; +} diff --git a/src/data/accountData.h b/src/data/accountData.h new file mode 100644 index 0000000..d91c969 --- /dev/null +++ b/src/data/accountData.h @@ -0,0 +1,29 @@ +// +// Created by quentin on 8/4/22. +// + +#ifndef BUDGET_ACCOUNTDATA_H +#define BUDGET_ACCOUNTDATA_H + + +#include "data.h" +#include "../money/account.h" + +static const char *jsonTemplate = ""; + +class AccountData : private Data { +public: + AccountData(const std::string &file); + + Account *getAccount(); + +private: + Account account; + + Account createObject() override; + + bool isJsonCorrect() override; +}; + + +#endif //BUDGET_ACCOUNTDATA_H diff --git a/src/data/data.h b/src/data/data.h new file mode 100644 index 0000000..70bffbf --- /dev/null +++ b/src/data/data.h @@ -0,0 +1,36 @@ +// +// Created by quentin on 8/4/22. +// + +#ifndef BUDGET_DATA_H +#define BUDGET_DATA_H + +#include +#include +#include +#include + +template +class Data { +public: + rapidjson::Document document; + + + Data(std::string file); + + virtual T createObject() = 0; + + std::string getFilePath(); + + +private: + const std::string fileName; + const std::string homeDirectory = getpwuid(getuid())->pw_dir; + std::string fileDirectory; + + virtual bool isJsonCorrect() = 0; +}; + +#include "data.tpp" + +#endif //BUDGET_DATA_H \ No newline at end of file diff --git a/src/data/data.tpp b/src/data/data.tpp new file mode 100644 index 0000000..e2a890a --- /dev/null +++ b/src/data/data.tpp @@ -0,0 +1,34 @@ +// +// Created by quentin on 8/4/22. +// + + +#include "data.h" + +#include +#include +#include + + +template +Data::Data(std::string file) : fileName(std::move(file)) { + // Create file if it doesnt exist + std::fstream fstream(getFilePath(), std::ios::out | std::ios::app); + fstream.close(); + + std::ifstream ifstream(getFilePath(), std::ios::in | std::ios::binary | std::ios::ate); + std::ifstream::pos_type fileSize = ifstream.tellg(); + ifstream.seekg(0, std::ios::beg); + + std::vector bytes(fileSize); + ifstream.read(bytes.data(), fileSize); + + document.Parse(std::string(bytes.data(), fileSize).c_str()); + + ifstream.close(); +} + +template +std::string Data::getFilePath() { + return fileName; +} diff --git a/src/main.cpp b/src/main.cpp index ac0d0de..d8be642 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -2,4 +2,30 @@ // Created by quentin on 8/3/22. // +#include "main.h" +#include "data/accountData.h" +#include +#include +#include +#include +#include +#include + +const std::string homeDirectory = getpwuid(getuid())->pw_dir; + +void createRequiredFolders() { + std::filesystem::create_directory(homeDirectory + "/.config/budget/"); + std::filesystem::create_directories(homeDirectory + "/.local/share/budget"); + std::filesystem::create_directories(homeDirectory + "/.local/share/budget/accounts"); +} + +int main() { + createRequiredFolders(); + std::list accounts; + for (const auto &file : std::filesystem::directory_iterator( + homeDirectory + "/.local/share/budget/accounts")) { + accounts.emplace_back(AccountData(file.path())); + } + return 0; +} diff --git a/src/main.h b/src/main.h new file mode 100644 index 0000000..7f6116b --- /dev/null +++ b/src/main.h @@ -0,0 +1,8 @@ +// +// Created by quentin on 8/12/22. +// + +#ifndef BUDGET_MAIN_H +#define BUDGET_MAIN_H + +#endif //BUDGET_MAIN_H diff --git a/src/money/account.cpp b/src/money/account.cpp index fbfe0d5..5806d3b 100644 --- a/src/money/account.cpp +++ b/src/money/account.cpp @@ -4,6 +4,14 @@ #include "account.h" -account::account(const bool withdrawable) : withdrawable(withdrawable) { - +#include + +Account::Account(std::list transactions, std::list earnings, bool withdrawable, + std::string name) : transactions(std::move(transactions)), earnings(std::move(earnings)), + withdrawable(withdrawable), + name(std::move(name)) {} + +Account::Account() { + withdrawable = true; + name = ""; } diff --git a/src/money/account.h b/src/money/account.h index d872d6e..c592f59 100644 --- a/src/money/account.h +++ b/src/money/account.h @@ -6,14 +6,23 @@ #define BUDGET_ACCOUNT_H -class account { +#include "transaction.h" +#include "earning.h" +#include +#include + +class Account { public: - account(const bool withdrawable); - const bool withdrawable; + Account(std::list transactions, std::list earnings, bool withdrawable, + std::string name); + Account(); + private: - std::list<> assets; - + std::list transactions; + std::list earnings; + bool withdrawable; + std::string name; }; diff --git a/src/money/earning.cpp b/src/money/earning.cpp new file mode 100644 index 0000000..6e9c68e --- /dev/null +++ b/src/money/earning.cpp @@ -0,0 +1,7 @@ +// +// Created by quentin on 8/11/22. +// + +#include "earning.h" + +Earning::Earning(const int value) : value(value) {} diff --git a/src/money/earning.h b/src/money/earning.h new file mode 100644 index 0000000..5b2f862 --- /dev/null +++ b/src/money/earning.h @@ -0,0 +1,18 @@ +// +// Created by quentin on 8/11/22. +// + +#ifndef BUDGET_EARNING_H +#define BUDGET_EARNING_H + + +class Earning { +public: + explicit Earning(int value); + +public: + const int value; +}; + + +#endif //BUDGET_EARNING_H diff --git a/src/money/recept.cpp b/src/money/recept.cpp new file mode 100644 index 0000000..69e4fe6 --- /dev/null +++ b/src/money/recept.cpp @@ -0,0 +1,9 @@ +// +// Created by quentin on 8/4/22. +// + +#include "recept.h" + +#include + +Receipt::Receipt(std::string file) : file(std::move(file)) {} diff --git a/src/money/recept.h b/src/money/recept.h new file mode 100644 index 0000000..61fe008 --- /dev/null +++ b/src/money/recept.h @@ -0,0 +1,21 @@ +// +// Created by quentin on 8/4/22. +// + +#ifndef BUDGET_RECEPT_H +#define BUDGET_RECEPT_H + + +#include + +class Receipt { +private: +public: + explicit Receipt(std::string file); + +private: + std::string file; +}; + + +#endif //BUDGET_RECEPT_H diff --git a/src/money/transaction.cpp b/src/money/transaction.cpp new file mode 100644 index 0000000..aba060e --- /dev/null +++ b/src/money/transaction.cpp @@ -0,0 +1,13 @@ +// +// Created by quentin on 8/4/22. +// + +#include "transaction.h" + +#include + +Receipt &Transaction::getReceipt() { + return receipt; +} + +Transaction::Transaction(const int value, Receipt receipt) : value(value), receipt(std::move(receipt)) {} diff --git a/src/money/transaction.h b/src/money/transaction.h new file mode 100644 index 0000000..716b8b8 --- /dev/null +++ b/src/money/transaction.h @@ -0,0 +1,25 @@ +// +// Created by quentin on 8/4/22. +// + +#ifndef BUDGET_TRANSACTION_H +#define BUDGET_TRANSACTION_H + + +#include "recept.h" + +class Transaction { +public: + Transaction(int value, Receipt receipt); + + Receipt &getReceipt(); + +public: + const int value; + +private: + Receipt receipt; +}; + + +#endif //BUDGET_TRANSACTION_H