From 49146e031e2ad3d5d6dca8a799331f87c39dc84e Mon Sep 17 00:00:00 2001 From: Quentin Snow Date: Sun, 23 Apr 2023 12:52:09 -0500 Subject: [PATCH] accountOperation now gets earnings and payments, then sorts --- src/database.cpp | 78 ++++++++++++++++++++++++++-- src/database.h | 7 +++ src/models/earning.h | 10 +++- src/models/money.cpp | 5 ++ src/models/money.h | 2 + src/models/payment.h | 16 ++++-- src/models/transaction.h | 9 +++- src/optHandlers/accountOperation.cpp | 22 ++++++++ 8 files changed, 140 insertions(+), 9 deletions(-) diff --git a/src/database.cpp b/src/database.cpp index 4469411..8c14fcf 100644 --- a/src/database.cpp +++ b/src/database.cpp @@ -19,8 +19,8 @@ Budget::Models::Account Database::getAccount(const std::string &accountName, sql if (rc == SQLITE_ROW) { long long id = sqlite3_column_int64(stmt, 0); - char *name = (char *) (sqlite3_column_text(stmt, 1)); - char *description = (char *) sqlite3_column_text(stmt, 2); + std::string name = (char *) (sqlite3_column_text(stmt, 1)); + std::string description = (sqlite3_column_type(stmt, 2) == SQLITE_NULL) ? "" : (char*) sqlite3_column_text(stmt, 2); if (sqlite3_column_type(stmt, 3) == SQLITE_NULL || sqlite3_column_type(stmt, 4) == SQLITE_NULL) { sqlite3_finalize(stmt); return {id, name, description, nullptr}; @@ -195,4 +195,76 @@ Database::pay(Budget::Models::Account *account, Budget::OptHandlers::PaymentOper cacheAccountValue(account, db); return sqlite3_last_insert_rowid(db); -} \ No newline at end of file +} + +std::list +Database::getEarnings(Budget::Models::Account *account, long long int dateStart, long long int dateEnd, sqlite3 *db) { + sqlite3_stmt *stmt; + int rc = sqlite3_prepare_v2(db, + "SELECT * FROM earning WHERE accountId = ? AND date BETWEEN ? AND ?;", -1, &stmt, nullptr); + + if (rc != SQLITE_OK) + throw std::runtime_error("Failed preparing getEarnings statement"); + + sqlite3_bind_int64(stmt, 1, account->id); + sqlite3_bind_int64(stmt, 2, dateStart); + sqlite3_bind_int64(stmt, 3, dateEnd); + + rc = sqlite3_step(stmt); + + std::list earnings; + while (rc == SQLITE_ROW) { + long long id = sqlite3_column_int64(stmt, 0); + long long dollars = sqlite3_column_int64(stmt, 1); + long long cents = sqlite3_column_int64(stmt, 2); + std::string description = (sqlite3_column_type(stmt, 3) == SQLITE_NULL) ? "" : (char*) sqlite3_column_text(stmt, 3); + std::string receipt = (sqlite3_column_type(stmt, 4) == SQLITE_NULL) ? "" : (char*) sqlite3_column_text(stmt, 4); + long long accountId = sqlite3_column_int64(stmt, 5); + long long date = sqlite3_column_int64(stmt, 6); + + earnings.emplace_back(Budget::Models::Earning(id, {dollars, cents}, description, receipt, accountId, date)); + rc = sqlite3_step(stmt); + } + sqlite3_finalize(stmt); + + if (rc != SQLITE_DONE) + throw std::runtime_error("Failed getting all earnings from getEarnings"); + + return earnings; +} + +std::list +Database::getPayments(Budget::Models::Account *account, long long int dateStart, long long int dateEnd, sqlite3 *db) { + sqlite3_stmt *stmt; + int rc = sqlite3_prepare_v2(db, + "SELECT * FROM payment WHERE accountId = ? AND date BETWEEN ? AND ?;", -1, &stmt, nullptr); + + if (rc != SQLITE_OK) + throw std::runtime_error("Failed preparing getPayments statement"); + + sqlite3_bind_int64(stmt, 1, account->id); + sqlite3_bind_int64(stmt, 2, dateStart); + sqlite3_bind_int64(stmt, 3, dateEnd); + + rc = sqlite3_step(stmt); + + std::list earnings; + while (rc == SQLITE_ROW) { + long long id = sqlite3_column_int64(stmt, 0); + long long dollars = sqlite3_column_int64(stmt, 1); + long long cents = sqlite3_column_int64(stmt, 2); + std::string description = (sqlite3_column_type(stmt, 3) == SQLITE_NULL) ? "" : (char*) sqlite3_column_text(stmt, 3); + std::string receipt = (sqlite3_column_type(stmt, 4) == SQLITE_NULL) ? "" : (char*) sqlite3_column_text(stmt, 4); + long long accountId = sqlite3_column_int64(stmt, 5); + long long date = sqlite3_column_int64(stmt, 6); + + earnings.emplace_back(Budget::Models::Payment(id, {dollars, cents}, description, receipt, accountId, date)); + rc = sqlite3_step(stmt); + } + sqlite3_finalize(stmt); + + if (rc != SQLITE_DONE) + throw std::runtime_error("Failed getting all payments from getPayments"); + + return earnings; +} diff --git a/src/database.h b/src/database.h index de2d966..67b7522 100644 --- a/src/database.h +++ b/src/database.h @@ -9,9 +9,12 @@ #include "optHandlers/createOperation.h" #include "optHandlers/earnOperation.h" #include "optHandlers/paymentOperation.h" +#include "models/earning.h" +#include "models/payment.h" #include #include +#include class Database { public: @@ -112,6 +115,10 @@ public: */ static long long int pay(Budget::Models::Account *account, Budget::OptHandlers::PaymentOperation::Flags *flags, sqlite3 *db); + + static std::list getEarnings(Budget::Models::Account *account, long long dateStart, long long dateEnd, sqlite3 *db); + + static std::list getPayments(Budget::Models::Account *account, long long dateStart, long long dateEnd, sqlite3 *db); }; diff --git a/src/models/earning.h b/src/models/earning.h index 2cb4619..d0349a9 100644 --- a/src/models/earning.h +++ b/src/models/earning.h @@ -8,7 +8,15 @@ #include "transaction.h" namespace Budget::Models { - class Earning : Transaction { + class Earning : public Transaction { + public: + Earning(long long int id, const Money &value, const std::string &description, const std::string &receipt, + long long int accountId, long long int date) : Transaction(id, value, description, receipt, accountId, + date) {} + + Money getAdjustedMoney() override { + return value; + }; }; } diff --git a/src/models/money.cpp b/src/models/money.cpp index 6d84ed7..4973d5f 100644 --- a/src/models/money.cpp +++ b/src/models/money.cpp @@ -30,6 +30,11 @@ bool operator<(const Money &lhs, const Money &rhs) { return lhs.getDollars() * 100 + lhs.getCents() < rhs.getDollars() * 100 + rhs.getCents(); } +Money Budget::Models::operator*(const Money &lhs, int rhs) { + long long total_cents = (lhs.getDollars() * 100 + lhs.getCents()) * rhs; + return {total_cents / 100, std::abs(total_cents % 100)}; +} + std::ostream &operator<<(std::ostream &os, const Money &money) { os << "$" << money.getDollars() << "."; if (std::abs(money.getCents()) < 10) { diff --git a/src/models/money.h b/src/models/money.h index 363cbdf..4cc61a2 100644 --- a/src/models/money.h +++ b/src/models/money.h @@ -23,6 +23,8 @@ namespace Budget::Models { friend Money operator-(const Money &lhs, const Money &rhs); + friend Money operator*(const Money &lhs, int rhs); + friend bool operator==(const Money &lhs, const Money &rhs); friend bool operator<(const Money &lhs, const Money &rhs); diff --git a/src/models/payment.h b/src/models/payment.h index a8cdd18..79a7593 100644 --- a/src/models/payment.h +++ b/src/models/payment.h @@ -2,14 +2,22 @@ // Created by quentin on 2/2/23. // -#ifndef BUDGET_EARNING_H -#define BUDGET_EARNING_H +#ifndef BUDGET_PAYMENT_H +#define BUDGET_PAYMENT_H #include "transaction.h" namespace Budget::Models { - class Payment : Transaction { + class Payment : public Transaction { + public: + Payment(long long int id, const Money &value, const std::string &description, const std::string &receipt, + long long int accountId, long long int date) : Transaction(id, value, description, receipt, accountId, + date) {} + + Money getAdjustedMoney() override { + return value * -1; + } }; } -#endif //BUDGET_EARNING_H +#endif //BUDGET_PAYMENT_H diff --git a/src/models/transaction.h b/src/models/transaction.h index 23bad71..a748e77 100644 --- a/src/models/transaction.h +++ b/src/models/transaction.h @@ -9,9 +9,16 @@ namespace Budget::Models { class Transaction { + public: + Transaction(long long int id, const Money &value, std::string description, std::string receipt, + long long int accountId, long long int date) : id(id), value(value), description(std::move(description)), + receipt(std::move(receipt)), accountId(accountId), date(date) {}; + + virtual Money getAdjustedMoney() = 0; + public: long long int id; - long double value; + Money value; std::string description; std::string receipt; long long int accountId; diff --git a/src/optHandlers/accountOperation.cpp b/src/optHandlers/accountOperation.cpp index bdc1d67..99740af 100644 --- a/src/optHandlers/accountOperation.cpp +++ b/src/optHandlers/accountOperation.cpp @@ -9,12 +9,34 @@ #include #include +#include +#include using namespace Budget::OptHandlers; void AccountOperation::commit() { Budget::Models::Account account = Database::getAccount(accountName, db); + if (!flags.value && !flags.forceDel && !flags.del && flags.description.empty()) { + std::list earnings = Database::getEarnings(&account, 5, 8, db); + std::list payments = Database::getPayments(&account, 5, 8, db); + + std::list> mergedList; + for (Models::Earning &earning : earnings) { + mergedList.push_back(std::make_unique(earning)); + } + for (Models::Payment &payment : payments) { + mergedList.push_back(std::make_unique(payment)); + } + mergedList.sort([](const std::unique_ptr& a, const std::unique_ptr& b) { + return a->date < b->date; + }); + + std::cout << "Account: " << account.name << std::endl; + std::cout << std::string(account.name.size()+9, '-') << std::endl; + + + } if (flags.value) { if (account.cachedValue == nullptr) {