From 30290fc317711a15669eaa7af26eb27a97f972bf Mon Sep 17 00:00:00 2001 From: Quentin Snow Date: Sat, 28 Jan 2023 12:05:35 -0600 Subject: [PATCH] Earn and pay now recache value for account --- src/database.cpp | 44 +++++++++++++++++++++++++++++++++++++++++++- src/database.h | 12 ++++++++++++ 2 files changed, 55 insertions(+), 1 deletion(-) diff --git a/src/database.cpp b/src/database.cpp index 3f1ca90..5c7bd88 100644 --- a/src/database.cpp +++ b/src/database.cpp @@ -108,6 +108,45 @@ double Database::cacheAccountValue(long long accountId, sqlite3 *db) { throw std::runtime_error("Failed to set cashedValue for " + std::to_string(accountId)); } +double Database::cacheAccountValue(const std::string &account, sqlite3 *db) { + sqlite3_stmt *stmt; + int rc = sqlite3_prepare_v2(db, "SELECT SUM(value) FROM (" + "SELECT value * -1 as value FROM payment WHERE " + "(SELECT id FROM account where name = ?) " + "UNION ALL " + "SELECT value FROM earning WHERE " + "(SELECT id FROM account where name = ?));", -1, &stmt, nullptr); + + if (rc != SQLITE_OK) + throw std::runtime_error("Failed preparing get cashedValue " + account); + + sqlite3_bind_text(stmt, 1, account.c_str(), -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, 2, account.c_str(), -1, SQLITE_TRANSIENT); + + rc = sqlite3_step(stmt); + + double value; + if (rc == SQLITE_ROW) + value = sqlite3_column_double(stmt, 0); + else if (rc == SQLITE_DONE) + value = 0; + else + throw std::runtime_error("Failed get cashedValue " + account); + + sqlite3_reset(stmt); + rc = sqlite3_prepare_v2(db, "UPDATE account SET cachedValue = ? WHERE name = ?", -1, &stmt, nullptr); + if (rc != SQLITE_OK) + throw std::runtime_error("Failed preparing set cashedValue " + account); + + sqlite3_bind_double(stmt, 1, value); + sqlite3_bind_text(stmt, 2, account.c_str(), -1, SQLITE_TRANSIENT); + + rc = sqlite3_step(stmt); + if (rc == SQLITE_DONE) + return value; + throw std::runtime_error("Failed to set cashedValue for " + account); +} + void Database::accountDescription(const std::string &account, const std::string &description, sqlite3 *db) { sqlite3_stmt *stmt; int rc = sqlite3_prepare_v2(db, "UPDATE account SET description = ? WHERE name = ?", -1, &stmt, nullptr); @@ -162,7 +201,8 @@ void Database::earn(const std::string &account, long double &value, std::string long long date, sqlite3 *db) { sqlite3_stmt *stmt; int rc = sqlite3_prepare_v2(db, "INSERT INTO earning (value, description, receipt, accountId, date) VALUES " - "(?, ?, ?, (SELECT id FROM account WHERE name = ?), ?)", -1, &stmt, nullptr); + "(?, ?, ?, (SELECT id FROM account WHERE name = ?), ?);" + "SELECT cachedValue FROM account WHERE name = ?;", -1, &stmt, nullptr); if (rc != SQLITE_OK) throw std::runtime_error("Failed preparing earn statement"); @@ -178,6 +218,7 @@ void Database::earn(const std::string &account, long double &value, std::string if (rc != SQLITE_DONE) throw std::runtime_error("Failed to create earning"); + cacheAccountValue(account, db); } void Database::pay(const std::string &account, long double &value, std::string &description, std::string &receipt, @@ -200,4 +241,5 @@ void Database::pay(const std::string &account, long double &value, std::string & if (rc != SQLITE_DONE) throw std::runtime_error("Failed to create payment"); + cacheAccountValue(account, db); } \ No newline at end of file diff --git a/src/database.h b/src/database.h index 34929de..4b98ee2 100644 --- a/src/database.h +++ b/src/database.h @@ -59,6 +59,18 @@ public: */ static double cacheAccountValue(long long accountId, sqlite3 *db); + /** + * @brief Caches the value of an account by calculating the sum of all payments and earnings + * + * @param account The name of the account to cache the value of + * @param db The database connection to use + * + * @return The cached value of the account + * + * @throws std::runtime_error If the database query fails + */ + static double cacheAccountValue(const std::string &account, sqlite3 *db); + /** * @brief Sets a new description for an account *