Payments and earns now store their receipts.
The database tables are now created on startup
This commit is contained in:
parent
c81bddf79a
commit
0d6a22fb8b
@ -24,7 +24,9 @@ set(HEADERS
|
||||
src/database.h
|
||||
src/exceptions/helpRequested.h
|
||||
src/exceptions/badValue.h
|
||||
src/utilities.h src/sqliteDb.h)
|
||||
src/utilities.h
|
||||
src/sqliteDb.h
|
||||
src/main.h)
|
||||
|
||||
|
||||
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
|
||||
|
@ -197,12 +197,12 @@ void Database::createAccount(const std::string &account, sqlite3 *db) {
|
||||
throw std::runtime_error("Failed to create account " + account);
|
||||
}
|
||||
|
||||
void Database::earn(const std::string &account, long double &value, std::string &description, std::string &receipt,
|
||||
long long int Database::earn(const std::string &account, long double &value, std::string &description, std::string &receipt,
|
||||
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 = ?), ?);"
|
||||
"SELECT cachedValue FROM account WHERE name = ?;", -1, &stmt, nullptr);
|
||||
"(?, ?, ?, (SELECT id FROM account WHERE name = ?), ?);",
|
||||
-1, &stmt, nullptr);
|
||||
|
||||
if (rc != SQLITE_OK)
|
||||
throw std::runtime_error("Failed preparing earn statement");
|
||||
@ -219,13 +219,16 @@ 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);
|
||||
|
||||
return sqlite3_last_insert_rowid(db);
|
||||
}
|
||||
|
||||
void Database::pay(const std::string &account, long double &value, std::string &description, std::string &receipt,
|
||||
long long int Database::pay(const std::string &account, long double &value, std::string &description, std::string &receipt,
|
||||
long long date, sqlite3 *db) {
|
||||
sqlite3_stmt *stmt;
|
||||
int rc = sqlite3_prepare_v2(db, "INSERT INTO payment (value, description, receipt, accountId, date) VALUES "
|
||||
"(?, ?, ?, (SELECT id FROM account WHERE name = ?), ?)", -1, &stmt, nullptr);
|
||||
"(?, ?, ?, (SELECT id FROM account WHERE name = ?), ?);",
|
||||
-1, &stmt, nullptr);
|
||||
|
||||
if (rc != SQLITE_OK)
|
||||
throw std::runtime_error("Failed preparing pay statement");
|
||||
@ -242,4 +245,6 @@ 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);
|
||||
|
||||
return sqlite3_last_insert_rowid(db);
|
||||
}
|
@ -119,7 +119,7 @@ public:
|
||||
* The accountId is retrieved from the 'account' table using the provided account name.
|
||||
* If the query fails to prepare or execute, the function throws a runtime_error.
|
||||
*/
|
||||
static void
|
||||
static long long int
|
||||
earn(const std::string &account, long double &value, std::string &description, std::string &receipt,
|
||||
long long int date,
|
||||
sqlite3 *db);
|
||||
@ -140,7 +140,7 @@ public:
|
||||
* The accountId is retrieved from the 'account' table using the provided account name.
|
||||
* If the query fails to prepare or execute, the function throws a runtime_error.
|
||||
*/
|
||||
static void
|
||||
static long long int
|
||||
pay(const std::string &account, long double &value, std::string &description, std::string &receipt,
|
||||
long long int date,
|
||||
sqlite3 *db);
|
||||
|
22
src/main.cpp
22
src/main.cpp
@ -6,9 +6,8 @@
|
||||
#include "exceptions/helpRequested.h"
|
||||
#include "exceptions/badValue.h"
|
||||
#include "sqliteDb.h"
|
||||
#include "main.h"
|
||||
|
||||
#include <pwd.h>
|
||||
#include <unistd.h>
|
||||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <sqlite3.h>
|
||||
@ -17,19 +16,24 @@
|
||||
|
||||
using namespace Budget;
|
||||
|
||||
const std::string homeDirectory = getpwuid(getuid())->pw_dir;
|
||||
const std::string configD = homeDirectory + "/.config/budget/";
|
||||
const std::string storageD = homeDirectory + "/.local/share/budget/";
|
||||
const std::string databaseFile = homeDirectory + "/.local/share/budget/budget.sqlite";
|
||||
|
||||
const char* createTables = "CREATE TABLE account (id INTEGER CONSTRAINT account_pk PRIMARY KEY AUTOINCREMENT, name TEXT, description TEXT, cachedValue DOUBLE);"
|
||||
"CREATE UNIQUE INDEX account_name_uindex ON account (name);"
|
||||
"CREATE TABLE earning (id INTEGER CONSTRAINT earning_pk PRIMARY KEY AUTOINCREMENT, value DOUBLE NOT NULL, description TEXT, receipt TEXT, accountId INT NOT NULL REFERENCES account ON UPDATE CASCADE ON DELETE CASCADE, date INTEGER NOT NULL);"
|
||||
"CREATE INDEX earning_date_index ON earning (date DESC);"
|
||||
"CREATE TABLE payment (id INTEGER CONSTRAINT payment_pk PRIMARY KEY AUTOINCREMENT, value DOUBLE NOT NULL, description TEXT, receipt TEXT, accountId INT NOT NULL REFERENCES account ON UPDATE CASCADE ON DELETE CASCADE, date INTEGER NOT NULL);"
|
||||
"CREATE INDEX payment_date_index ON payment (date DESC);";
|
||||
|
||||
void createRequiredFolders() {
|
||||
std::filesystem::create_directory(configD);
|
||||
std::filesystem::create_directories(storageD);
|
||||
std::filesystem::create_directories(storageD + "receipts");
|
||||
std::filesystem::create_directories(storageD + "receipts/payment");
|
||||
std::filesystem::create_directories(storageD + "receipts/earn");
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
createRequiredFolders();
|
||||
|
||||
sqlite3 *db;
|
||||
SqliteDb dbRAII(db);
|
||||
|
||||
@ -47,6 +51,10 @@ int main(int argc, char *argv[]) {
|
||||
if (rc != SQLITE_OK)
|
||||
throw std::runtime_error("Couldn't begin transaction");
|
||||
|
||||
rc = sqlite3_exec(db, createTables, nullptr, nullptr, nullptr);
|
||||
if (rc != SQLITE_OK)
|
||||
throw std::runtime_error("Couldn't create the tables");
|
||||
|
||||
std::vector<char *> args(argv, argv + argc);
|
||||
try {
|
||||
OptHandlers::MainOptHandler moh(args, db);
|
||||
|
17
src/main.h
Normal file
17
src/main.h
Normal file
@ -0,0 +1,17 @@
|
||||
//
|
||||
// Created by quentin on 1/31/23.
|
||||
//
|
||||
|
||||
#ifndef BUDGET_MAIN_H
|
||||
#define BUDGET_MAIN_H
|
||||
|
||||
#include <unistd.h>
|
||||
#include <pwd.h>
|
||||
|
||||
const static std::string homeDirectory = getpwuid(getuid())->pw_dir;
|
||||
const static std::string configD = homeDirectory + "/.config/budget/";
|
||||
const static std::string storageD = homeDirectory + "/.local/share/budget/";
|
||||
const static std::string databaseFile = homeDirectory + "/.local/share/budget/budget.sqlite";
|
||||
|
||||
|
||||
#endif //BUDGET_MAIN_H
|
@ -2,9 +2,11 @@
|
||||
// Created by quentin on 1/17/23.
|
||||
//
|
||||
|
||||
#include <fstream>
|
||||
#include "PaymentOperation.h"
|
||||
#include "../database.h"
|
||||
#include "../exceptions/badValue.h"
|
||||
#include "../main.h"
|
||||
|
||||
using namespace Budget::OptHandlers;
|
||||
|
||||
@ -12,7 +14,21 @@ void PaymentOperation::commit() {
|
||||
if (!Database::doesAccountExist(account, db))
|
||||
throw Budget::Exceptions::BadValue("Account " + account + " doesn't exist");
|
||||
|
||||
Database::pay(account, flags.value, flags.description, flags.receipt, flags.date, db);
|
||||
long long id = Database::pay(account, flags.value, flags.description, flags.receipt, flags.date, db);
|
||||
|
||||
if (!flags.receipt.empty()) {
|
||||
std::string extension;
|
||||
size_t pos = flags.receipt.find_last_of('.');
|
||||
if (pos != std::string::npos) {
|
||||
extension = flags.receipt.substr(pos);
|
||||
}
|
||||
|
||||
std::ifstream source(flags.receipt, std::ios::binary);
|
||||
std::ofstream dest(storageD + "receipts/payment/" + std::to_string(id) + extension, std::ios::binary);
|
||||
dest << source.rdbuf();
|
||||
source.close();
|
||||
dest.close();
|
||||
}
|
||||
}
|
||||
|
||||
PaymentOperation::PaymentOperation(sqlite3 *db, std::string account) : Operation(db), account(std::move(account)) {}
|
@ -2,9 +2,11 @@
|
||||
// Created by quentin on 1/17/23.
|
||||
//
|
||||
|
||||
#include <fstream>
|
||||
#include "earnOperation.h"
|
||||
#include "../database.h"
|
||||
#include "../exceptions/badValue.h"
|
||||
#include "../main.h"
|
||||
|
||||
using namespace Budget::OptHandlers;
|
||||
|
||||
@ -12,7 +14,21 @@ void EarnOperation::commit() {
|
||||
if (!Database::doesAccountExist(account, db))
|
||||
throw Budget::Exceptions::BadValue("Account " + account + " doesn't exist");
|
||||
|
||||
Database::earn(account, flags.value, flags.description, flags.receipt, flags.date, db);
|
||||
long long id = Database::pay(account, flags.value, flags.description, flags.receipt, flags.date, db);
|
||||
|
||||
if (!flags.receipt.empty()) {
|
||||
std::string extension;
|
||||
size_t pos = flags.receipt.find_last_of('.');
|
||||
if (pos != std::string::npos) {
|
||||
extension = flags.receipt.substr(pos);
|
||||
}
|
||||
|
||||
std::ifstream source(flags.receipt, std::ios::binary);
|
||||
std::ofstream dest(storageD + "receipts/receipt/" + std::to_string(id) + extension, std::ios::binary);
|
||||
dest << source.rdbuf();
|
||||
source.close();
|
||||
dest.close();
|
||||
}
|
||||
}
|
||||
|
||||
EarnOperation::EarnOperation(sqlite3 *db, std::string account) : Operation(db), account(std::move(account)) {}
|
Loading…
x
Reference in New Issue
Block a user