Compare commits

..

No commits in common. "49146e031e2ad3d5d6dca8a799331f87c39dc84e" and "aa7c830036125ece290c3d9183024255c3078598" have entirely different histories.

15 changed files with 59 additions and 201 deletions

View File

@ -19,8 +19,8 @@ Budget::Models::Account Database::getAccount(const std::string &accountName, sql
if (rc == SQLITE_ROW) { if (rc == SQLITE_ROW) {
long long id = sqlite3_column_int64(stmt, 0); long long id = sqlite3_column_int64(stmt, 0);
std::string name = (char *) (sqlite3_column_text(stmt, 1)); char* name = (char*)(sqlite3_column_text(stmt, 1));
std::string description = (sqlite3_column_type(stmt, 2) == SQLITE_NULL) ? "" : (char*) sqlite3_column_text(stmt, 2); char* description = (char*)sqlite3_column_text(stmt, 2);
if (sqlite3_column_type(stmt, 3) == SQLITE_NULL || sqlite3_column_type(stmt, 4) == SQLITE_NULL) { if (sqlite3_column_type(stmt, 3) == SQLITE_NULL || sqlite3_column_type(stmt, 4) == SQLITE_NULL) {
sqlite3_finalize(stmt); sqlite3_finalize(stmt);
return {id, name, description, nullptr}; return {id, name, description, nullptr};
@ -55,12 +55,10 @@ void Database::deleteAccount(Budget::Models::Account *account, sqlite3 *db) {
void Database::cacheAccountValue(Budget::Models::Account *account, sqlite3 *db) { void Database::cacheAccountValue(Budget::Models::Account *account, sqlite3 *db) {
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
int rc = sqlite3_prepare_v2(db, int rc = sqlite3_prepare_v2(db, "SELECT SUM(dollars * 100 + cents) / 100 as nDollars, SUM(dollars * 100 + cents) % 100 as nCents FROM("
"SELECT SUM(dollars * 100 + cents) / 100 as nDollars, SUM(dollars * 100 + cents) % 100 as nCents FROM("
"SELECT SUM(dollars * 100 + cents) / 100 AS dollars, SUM(dollars * 100 + cents) % 100 AS cents FROM earning WHERE accountId = ? " "SELECT SUM(dollars * 100 + cents) / 100 AS dollars, SUM(dollars * 100 + cents) % 100 AS cents FROM earning WHERE accountId = ? "
"UNION ALL " "UNION ALL "
"SELECT SUM(dollars * 100 + cents) / 100 * -1 AS dollars, SUM(dollars * 100 + cents) % 100 * -1 AS cents FROM payment WHERE accountId = ?);", "SELECT SUM(dollars * 100 + cents) / 100 * -1 AS dollars, SUM(dollars * 100 + cents) % 100 * -1 AS cents FROM payment WHERE accountId = ?);", -1, &stmt, nullptr);
-1, &stmt, nullptr);
if (rc != SQLITE_OK) if (rc != SQLITE_OK)
throw std::runtime_error("Failed preparing get cashedValue " + account->name); throw std::runtime_error("Failed preparing get cashedValue " + account->name);
@ -75,15 +73,16 @@ void Database::cacheAccountValue(Budget::Models::Account *account, sqlite3 *db)
if (rc == SQLITE_ROW) { if (rc == SQLITE_ROW) {
dollars = sqlite3_column_int64(stmt, 0); dollars = sqlite3_column_int64(stmt, 0);
cents = sqlite3_column_int64(stmt, 1); cents = sqlite3_column_int64(stmt, 1);
} else if (rc == SQLITE_DONE) { }
else if (rc == SQLITE_DONE) {
dollars = 0; dollars = 0;
cents = 0; cents = 0;
} else }
else
throw std::runtime_error("Failed get cashedValue " + account->name); throw std::runtime_error("Failed get cashedValue " + account->name);
sqlite3_reset(stmt); sqlite3_reset(stmt);
rc = sqlite3_prepare_v2(db, "UPDATE account SET cachedDollars = ?, cachedCents = ? WHERE id = ?", -1, &stmt, rc = sqlite3_prepare_v2(db, "UPDATE account SET cachedDollars = ?, cachedCents = ? WHERE id = ?", -1, &stmt, nullptr);
nullptr);
if (rc != SQLITE_OK) if (rc != SQLITE_OK)
throw std::runtime_error("Failed preparing set cashedValue " + account->name); throw std::runtime_error("Failed preparing set cashedValue " + account->name);
@ -116,8 +115,7 @@ void Database::accountDescription(Budget::Models::Account *account, sqlite3 *db)
throw std::runtime_error("Failed to set description on " + account->name); throw std::runtime_error("Failed to set description on " + account->name);
} }
long long int long long int Database::createAccount(Budget::OptHandlers::CreateOperation::Flags *flags, std::string &account, sqlite3 *db) {
Database::createAccount(Budget::OptHandlers::CreateOperation::Flags *flags, std::string &account, sqlite3 *db) {
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
int rc = sqlite3_prepare_v2(db, "INSERT INTO account (name, description) VALUES (?, ?)", -1, &stmt, nullptr); int rc = sqlite3_prepare_v2(db, "INSERT INTO account (name, description) VALUES (?, ?)", -1, &stmt, nullptr);
@ -125,8 +123,7 @@ Database::createAccount(Budget::OptHandlers::CreateOperation::Flags *flags, std:
throw std::runtime_error("Failed preparing createAccount statement"); throw std::runtime_error("Failed preparing createAccount statement");
sqlite3_bind_text(stmt, 1, account.c_str(), -1, SQLITE_TRANSIENT); sqlite3_bind_text(stmt, 1, account.c_str(), -1, SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 2, (flags->description.empty() ? nullptr : flags->description.c_str()), -1, sqlite3_bind_text(stmt, 2, (flags->description.empty() ? nullptr : flags->description.c_str()), -1, SQLITE_TRANSIENT);
SQLITE_TRANSIENT);
rc = sqlite3_step(stmt); rc = sqlite3_step(stmt);
@ -139,11 +136,9 @@ Database::createAccount(Budget::OptHandlers::CreateOperation::Flags *flags, std:
return sqlite3_last_insert_rowid(db); return sqlite3_last_insert_rowid(db);
} }
long long int long long int Database::earn(Budget::Models::Account *account, Budget::OptHandlers::EarnOperation::Flags *flags, sqlite3 *db) {
Database::earn(Budget::Models::Account *account, Budget::OptHandlers::EarnOperation::Flags *flags, sqlite3 *db) {
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
int rc = sqlite3_prepare_v2(db, int rc = sqlite3_prepare_v2(db, "INSERT INTO earning (dollars, cents, description, receipt, accountId, date) VALUES "
"INSERT INTO earning (dollars, cents, description, receipt, accountId, date) VALUES "
"(?, ?, ?, ?, ?, ?);", "(?, ?, ?, ?, ?, ?);",
-1, &stmt, nullptr); -1, &stmt, nullptr);
@ -152,8 +147,7 @@ Database::earn(Budget::Models::Account *account, Budget::OptHandlers::EarnOperat
sqlite3_bind_int64(stmt, 1, flags->dollars); sqlite3_bind_int64(stmt, 1, flags->dollars);
sqlite3_bind_int64(stmt, 2, flags->cents); sqlite3_bind_int64(stmt, 2, flags->cents);
sqlite3_bind_text(stmt, 3, (flags->description.empty() ? nullptr : flags->description.c_str()), -1, sqlite3_bind_text(stmt, 3, (flags->description.empty() ? nullptr : flags->description.c_str()), -1, SQLITE_TRANSIENT);
SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, (flags->receipt.empty() ? nullptr : flags->receipt.c_str()), -1, SQLITE_TRANSIENT); sqlite3_bind_text(stmt, 4, (flags->receipt.empty() ? nullptr : flags->receipt.c_str()), -1, SQLITE_TRANSIENT);
sqlite3_bind_int64(stmt, 5, account->id); sqlite3_bind_int64(stmt, 5, account->id);
sqlite3_bind_int64(stmt, 6, flags->date); sqlite3_bind_int64(stmt, 6, flags->date);
@ -168,11 +162,9 @@ Database::earn(Budget::Models::Account *account, Budget::OptHandlers::EarnOperat
return sqlite3_last_insert_rowid(db); return sqlite3_last_insert_rowid(db);
} }
long long int long long int Database::pay(Budget::Models::Account *account, Budget::OptHandlers::PaymentOperation::Flags *flags, sqlite3 *db) {
Database::pay(Budget::Models::Account *account, Budget::OptHandlers::PaymentOperation::Flags *flags, sqlite3 *db) {
sqlite3_stmt *stmt; sqlite3_stmt *stmt;
int rc = sqlite3_prepare_v2(db, int rc = sqlite3_prepare_v2(db, "INSERT INTO payment (dollars, cents, description, receipt, accountId, date) VALUES "
"INSERT INTO payment (dollars, cents, description, receipt, accountId, date) VALUES "
"(?, ?, ?, ?, ?, ?);", "(?, ?, ?, ?, ?, ?);",
-1, &stmt, nullptr); -1, &stmt, nullptr);
@ -181,8 +173,7 @@ Database::pay(Budget::Models::Account *account, Budget::OptHandlers::PaymentOper
sqlite3_bind_int64(stmt, 1, flags->dollars); sqlite3_bind_int64(stmt, 1, flags->dollars);
sqlite3_bind_int64(stmt, 2, flags->cents); sqlite3_bind_int64(stmt, 2, flags->cents);
sqlite3_bind_text(stmt, 3, (flags->description.empty() ? nullptr : flags->description.c_str()), -1, sqlite3_bind_text(stmt, 3, (flags->description.empty() ? nullptr : flags->description.c_str()), -1, SQLITE_TRANSIENT);
SQLITE_TRANSIENT);
sqlite3_bind_text(stmt, 4, (flags->receipt.empty() ? nullptr : flags->receipt.c_str()), -1, SQLITE_TRANSIENT); sqlite3_bind_text(stmt, 4, (flags->receipt.empty() ? nullptr : flags->receipt.c_str()), -1, SQLITE_TRANSIENT);
sqlite3_bind_int64(stmt, 5, account->id); sqlite3_bind_int64(stmt, 5, account->id);
sqlite3_bind_int64(stmt, 6, flags->date); sqlite3_bind_int64(stmt, 6, flags->date);
@ -196,75 +187,3 @@ Database::pay(Budget::Models::Account *account, Budget::OptHandlers::PaymentOper
return sqlite3_last_insert_rowid(db); return sqlite3_last_insert_rowid(db);
} }
std::list<Budget::Models::Earning>
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<Budget::Models::Earning> 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<Budget::Models::Payment>
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<Budget::Models::Payment> 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;
}

View File

@ -9,12 +9,9 @@
#include "optHandlers/createOperation.h" #include "optHandlers/createOperation.h"
#include "optHandlers/earnOperation.h" #include "optHandlers/earnOperation.h"
#include "optHandlers/paymentOperation.h" #include "optHandlers/paymentOperation.h"
#include "models/earning.h"
#include "models/payment.h"
#include <string> #include <string>
#include <sqlite3.h> #include <sqlite3.h>
#include <list>
class Database { class Database {
public: public:
@ -74,8 +71,7 @@ public:
* *
* @throws std::runtime_error If the accountName could not be created in the database * @throws std::runtime_error If the accountName could not be created in the database
*/ */
static long long int static long long int createAccount(Budget::OptHandlers::CreateOperation::Flags *flags, std::string &account, sqlite3 *db);
createAccount(Budget::OptHandlers::CreateOperation::Flags *flags, std::string &account, sqlite3 *db);
/** /**
* @brief The function records an earning in the database * @brief The function records an earning in the database
@ -115,10 +111,6 @@ public:
*/ */
static long long int static long long int
pay(Budget::Models::Account *account, Budget::OptHandlers::PaymentOperation::Flags *flags, sqlite3 *db); pay(Budget::Models::Account *account, Budget::OptHandlers::PaymentOperation::Flags *flags, sqlite3 *db);
static std::list<Budget::Models::Earning> getEarnings(Budget::Models::Account *account, long long dateStart, long long dateEnd, sqlite3 *db);
static std::list<Budget::Models::Payment> getPayments(Budget::Models::Account *account, long long dateStart, long long dateEnd, sqlite3 *db);
}; };

View File

@ -8,16 +8,7 @@
#include "transaction.h" #include "transaction.h"
namespace Budget::Models { namespace Budget::Models {
class Earning : public Transaction { class Earning : 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;
};
};
} }
#endif //BUDGET_EARNING_H #endif //BUDGET_EARNING_H

View File

@ -17,6 +17,8 @@ Money operator+(const Money &lhs, const Money &rhs) {
return {total_dollars, total_cents}; return {total_dollars, total_cents};
} }
Money operator-(const Money &lhs, const Money &rhs) { Money operator-(const Money &lhs, const Money &rhs) {
long long total_cents = lhs.getDollars() * 100 + lhs.getCents() - rhs.getDollars() * 100 - rhs.getCents(); long long total_cents = lhs.getDollars() * 100 + lhs.getCents() - rhs.getDollars() * 100 - rhs.getCents();
return {total_cents / 100, std::abs(total_cents % 100)}; return {total_cents / 100, std::abs(total_cents % 100)};
@ -30,16 +32,11 @@ bool operator<(const Money &lhs, const Money &rhs) {
return lhs.getDollars() * 100 + lhs.getCents() < rhs.getDollars() * 100 + rhs.getCents(); 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) { std::ostream &operator<<(std::ostream &os, const Money &money) {
os << "$" << money.getDollars() << "."; os << "$" << money.getDollars() << ".";
if (std::abs(money.getCents()) < 10) { if (money.getCents() < 10) {
os << "0"; os << "0";
} }
os << std::abs(money.getCents()); os << money.getCents();
return os; return os;
} }

View File

@ -23,8 +23,6 @@ namespace Budget::Models {
friend Money operator-(const Money &lhs, const Money &rhs); 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);
friend bool operator<(const Money &lhs, const Money &rhs); friend bool operator<(const Money &lhs, const Money &rhs);
@ -35,7 +33,6 @@ namespace Budget::Models {
}; };
} }
std::ostream &operator<<(std::ostream &os, const Budget::Models::Money &money); std::ostream &operator<<(std::ostream &os, const Budget::Models::Money &money);
#endif //BUDGET_MONEY_H #endif //BUDGET_MONEY_H

View File

@ -2,22 +2,13 @@
// Created by quentin on 2/2/23. // Created by quentin on 2/2/23.
// //
#ifndef BUDGET_PAYMENT_H #ifndef BUDGET_EARNING_H
#define BUDGET_PAYMENT_H #define BUDGET_EARNING_H
#include "transaction.h" #include "transaction.h"
namespace Budget::Models { namespace Budget::Models {
class Payment : public Transaction { class Payment : 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_PAYMENT_H #endif //BUDGET_EARNING_H

View File

@ -9,16 +9,9 @@
namespace Budget::Models { namespace Budget::Models {
class Transaction { 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: public:
long long int id; long long int id;
Money value; long double value;
std::string description; std::string description;
std::string receipt; std::string receipt;
long long int accountId; long long int accountId;

View File

@ -9,34 +9,12 @@
#include <utility> #include <utility>
#include <iostream> #include <iostream>
#include <memory>
#include <algorithm>
using namespace Budget::OptHandlers; using namespace Budget::OptHandlers;
void AccountOperation::commit() { void AccountOperation::commit() {
Budget::Models::Account account = Database::getAccount(accountName, db); Budget::Models::Account account = Database::getAccount(accountName, db);
if (!flags.value && !flags.forceDel && !flags.del && flags.description.empty()) {
std::list<Models::Earning> earnings = Database::getEarnings(&account, 5, 8, db);
std::list<Models::Payment> payments = Database::getPayments(&account, 5, 8, db);
std::list<std::unique_ptr<Models::Transaction>> mergedList;
for (Models::Earning &earning : earnings) {
mergedList.push_back(std::make_unique<Models::Earning>(earning));
}
for (Models::Payment &payment : payments) {
mergedList.push_back(std::make_unique<Models::Payment>(payment));
}
mergedList.sort([](const std::unique_ptr<Models::Transaction>& a, const std::unique_ptr<Models::Transaction>& 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 (flags.value) {
if (account.cachedValue == nullptr) { if (account.cachedValue == nullptr) {

View File

@ -22,12 +22,12 @@ void EarnOperation::commit() {
extension = flags.receipt.substr(pos); extension = flags.receipt.substr(pos);
} }
std::ofstream dest(storageD + "receipts/receipt/" + std::to_string(account.id) + extension, std::ofstream dest(storageD + "receipts/receipt/" + std::to_string(account.id) + extension, std::ios::binary);
std::ios::binary);
dest << source.rdbuf(); dest << source.rdbuf();
source.close(); source.close();
dest.close(); dest.close();
} else { }
else {
throw Exceptions::BadValue("File " + flags.receipt + " does not exist"); throw Exceptions::BadValue("File " + flags.receipt + " does not exist");
} }
} }

View File

@ -22,12 +22,12 @@ void PaymentOperation::commit() {
extension = flags.receipt.substr(pos); extension = flags.receipt.substr(pos);
} }
std::ofstream dest(storageD + "receipts/receipt/" + std::to_string(account.id) + extension, std::ofstream dest(storageD + "receipts/receipt/" + std::to_string(account.id) + extension, std::ios::binary);
std::ios::binary);
dest << source.rdbuf(); dest << source.rdbuf();
source.close(); source.close();
dest.close(); dest.close();
} else { }
else {
throw Exceptions::BadValue("File " + flags.receipt + " does not exist"); throw Exceptions::BadValue("File " + flags.receipt + " does not exist");
} }
} }