accountOperation check if account exists in database

This commit is contained in:
Quentin Snow 2023-01-21 17:50:07 -06:00
parent 98db5681d8
commit c3dbabe42d
18 changed files with 165 additions and 34 deletions

View File

@ -11,7 +11,7 @@ set(SOURCES
src/optHandlers/createOperation.cpp src/optHandlers/createOperation.cpp
src/optHandlers/earnOperation.cpp src/optHandlers/earnOperation.cpp
src/optHandlers/PaymentOperation.cpp src/optHandlers/PaymentOperation.cpp
) src/database.cpp)
set(HEADERS set(HEADERS
src/optHandlers/mainOptHandler.h src/optHandlers/mainOptHandler.h
@ -20,6 +20,11 @@ set(HEADERS
src/optHandlers/createOperation.h src/optHandlers/createOperation.h
src/optHandlers/earnOperation.h src/optHandlers/earnOperation.h
src/optHandlers/PaymentOperation.h src/optHandlers/PaymentOperation.h
) src/database.h
src/exceptions/helpRequested.h
src/exceptions/badValue.h)
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
add_executable(${PROJECT_NAME} ${SOURCES} ${HEADERS})
target_link_libraries(${PROJECT_NAME} sqlite3)

30
src/database.cpp Normal file
View File

@ -0,0 +1,30 @@
//
// Created by quentin on 1/18/23.
//
#include "database.h"
#include <sqlite3.h>
#include <stdexcept>
bool Database::doesAccountExist(const std::string &account, sqlite3 *db) {
sqlite3_stmt *stmt;
int rc = sqlite3_prepare_v2(db, "SELECT * FROM account WHERE name = ?", -1, &stmt, nullptr);
if (rc != SQLITE_OK) {
throw std::runtime_error("Failed to create account existing query");
}
sqlite3_bind_text(stmt, 1, account.c_str(), -1, SQLITE_TRANSIENT);
rc = sqlite3_step(stmt);
sqlite3_finalize(stmt);
if (rc == SQLITE_ROW) {
return true;
} else if (rc == SQLITE_DONE) {
return false;
} else {
throw std::runtime_error("Failed to step account existing statement.");
}
}

18
src/database.h Normal file
View File

@ -0,0 +1,18 @@
//
// Created by quentin on 1/18/23.
//
#ifndef BUDGET_DATABASE_H
#define BUDGET_DATABASE_H
#include <string>
#include <sqlite3.h>
class Database {
public:
static bool doesAccountExist(const std::string &account, sqlite3 *db);
};
#endif //BUDGET_DATABASE_H

17
src/exceptions/badValue.h Normal file
View File

@ -0,0 +1,17 @@
//
// Created by quentin on 1/18/23.
//
#ifndef BUDGET_BADVALUE_H
#define BUDGET_BADVALUE_H
#include <stdexcept>
namespace Budget::Exceptions {
class BadValue : public std::runtime_error {
public:
explicit BadValue(const std::string &what_arg) : std::runtime_error(what_arg) {}
};
}
#endif //BUDGET_BADVALUE_H

View File

@ -0,0 +1,18 @@
//
// Created by quentin on 1/18/23.
//
#ifndef BUDGET_HELPREQUESTED_H
#define BUDGET_HELPREQUESTED_H
#include <stdexcept>
namespace Budget::Exceptions {
class HelpRequested : public std::runtime_error {
public:
explicit HelpRequested(const std::string &what_arg) : std::runtime_error(what_arg) {}
};
}
#endif //BUDGET_HELPREQUESTED_H

View File

@ -3,11 +3,15 @@
// //
#include "optHandlers/mainOptHandler.h" #include "optHandlers/mainOptHandler.h"
#include "exceptions/helpRequested.h"
#include "exceptions/badValue.h"
#include <pwd.h> #include <pwd.h>
#include <unistd.h> #include <unistd.h>
#include <string> #include <string>
#include <filesystem> #include <filesystem>
#include <sqlite3.h>
#include <iostream>
using namespace Budget; using namespace Budget;
@ -15,16 +19,41 @@ using namespace Budget;
const std::string homeDirectory = getpwuid(getuid())->pw_dir; const std::string homeDirectory = getpwuid(getuid())->pw_dir;
const std::string configD = homeDirectory + "/.config/budget/"; const std::string configD = homeDirectory + "/.config/budget/";
const std::string storageD = homeDirectory + "/.local/share/budget/"; const std::string storageD = homeDirectory + "/.local/share/budget/";
const std::string databaseFile = homeDirectory + "/.local/share/budget/budget.sqlite";
void createRequiredFolders() { void createRequiredFolders() {
std::filesystem::create_directory(configD); std::filesystem::create_directory(configD);
std::filesystem::create_directories(storageD); std::filesystem::create_directories(storageD);
std::filesystem::create_directories(storageD + "accounts");
std::filesystem::create_directories(storageD + "receipts"); std::filesystem::create_directories(storageD + "receipts");
} }
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
sqlite3 *db;
int rc;
rc = sqlite3_open(databaseFile.c_str(), &db);
if (rc != SQLITE_OK) {
throw std::runtime_error("Error opening database connection.");
}
std::vector<char *> args(argv, argv + argc); std::vector<char *> args(argv, argv + argc);
OptHandlers::MainOptHandler moh(args); try {
OptHandlers::MainOptHandler moh(args, db);
std::queue<std::unique_ptr<OptHandlers::Operation>> *opts = &moh.operations;
while (!opts->empty()) {
opts->front()->commit();
opts->pop();
}
} catch (const Budget::Exceptions::HelpRequested &e) {
return 0;
} catch (const Budget::Exceptions::BadValue &e) {
std::cout << e.what() << std::endl;
return 1;
}
return 0; return 0;
} }

View File

@ -10,6 +10,6 @@ void PaymentOperation::commit() {
//TODO This function will be called when the action needs to be done //TODO This function will be called when the action needs to be done
} }
PaymentOperation::PaymentOperation(std::string account) : account(std::move(account)) { PaymentOperation::PaymentOperation(sqlite3 *db, std::string account) : Operation(db), account(std::move(account)) {
} }

View File

@ -15,7 +15,7 @@ namespace Budget::OptHandlers {
public: public:
void commit() override; void commit() override;
explicit PaymentOperation(std::string account); explicit PaymentOperation(sqlite3 *db, std::string account);
struct Flags : public Operation::Flags { struct Flags : public Operation::Flags {
long double value; long double value;

View File

@ -3,15 +3,16 @@
// //
#include "accountOperation.h" #include "accountOperation.h"
#include "../database.h"
#include <utility> #include <utility>
using namespace Budget::OptHandlers; using namespace Budget::OptHandlers;
void AccountOperation::commit() { void AccountOperation::commit() {
//TODO This function will be called when the action needs to be done Database::doesAccountExist(account, db);
} }
AccountOperation::AccountOperation(std::string account) : account(std::move(account)) { AccountOperation::AccountOperation(sqlite3 *db, std::string account) : Operation(db), account(std::move(account)) {
} }

View File

@ -14,7 +14,7 @@ namespace Budget::OptHandlers {
public: public:
void commit() override; void commit() override;
explicit AccountOperation(std::string account); explicit AccountOperation(sqlite3 *db, std::string account);
struct Flags : public Operation::Flags { struct Flags : public Operation::Flags {
bool del = false; bool del = false;

View File

@ -10,6 +10,6 @@ void CreateOperation::commit() {
//TODO This function will be called when the action needs to be done //TODO This function will be called when the action needs to be done
} }
CreateOperation::CreateOperation(std::string account) : account(std::move(account)) { CreateOperation::CreateOperation(sqlite3 *db, std::string account) : Operation(db), account(std::move(account)) {
} }

View File

@ -13,7 +13,7 @@ namespace Budget::OptHandlers {
public: public:
void commit() override; void commit() override;
explicit CreateOperation(std::string account); explicit CreateOperation(sqlite3 *db, std::string account);
struct Flags : public Operation::Flags { struct Flags : public Operation::Flags {
std::string description; std::string description;

View File

@ -10,6 +10,6 @@ void EarnOperation::commit() {
//TODO This function will be called when the action needs to be done //TODO This function will be called when the action needs to be done
} }
EarnOperation::EarnOperation(std::string account) : account(std::move(account)) { EarnOperation::EarnOperation(sqlite3 *db, std::string account) : Operation(db), account(std::move(account)) {
} }

View File

@ -14,7 +14,7 @@ namespace Budget::OptHandlers {
public: public:
void commit() override; void commit() override;
explicit EarnOperation(std::string account); explicit EarnOperation(sqlite3 *db, std::string account);
struct Flags : public Operation::Flags { struct Flags : public Operation::Flags {
long double value; long double value;

View File

@ -6,13 +6,15 @@
#include "createOperation.h" #include "createOperation.h"
#include "earnOperation.h" #include "earnOperation.h"
#include "PaymentOperation.h" #include "PaymentOperation.h"
#include "../exceptions/helpRequested.h"
#include "../exceptions/badValue.h"
#include <iostream> #include <iostream>
#include <getopt.h> #include <getopt.h>
#include <cstring> #include <cstring>
using namespace Budget::OptHandlers; using namespace Budget::OptHandlers;
MainOptHandler::MainOptHandler(const std::vector<char *> &_argv) : argv(_argv) { MainOptHandler::MainOptHandler(const std::vector<char *> &_argv, sqlite3 *db) : argv(_argv), db(db) {
struct option actionLongOpts[] = { struct option actionLongOpts[] = {
{"help", no_argument, nullptr, 'h'}, {"help", no_argument, nullptr, 'h'},
{"account", required_argument, nullptr, 'a'}, {"account", required_argument, nullptr, 'a'},
@ -29,7 +31,7 @@ MainOptHandler::MainOptHandler(const std::vector<char *> &_argv) : argv(_argv) {
switch (opt) { switch (opt) {
case 'h': case 'h':
help(); help();
exit(0); throw Budget::Exceptions::HelpRequested("Help requested at main");
case 'a': case 'a':
accountOptHandler(optarg); accountOptHandler(optarg);
break; break;
@ -44,7 +46,7 @@ MainOptHandler::MainOptHandler(const std::vector<char *> &_argv) : argv(_argv) {
break; break;
case '?': case '?':
help(); help();
exit(0); throw Budget::Exceptions::HelpRequested("Help requested at main, unknown argument.");
default: default:
break; break;
} }
@ -65,7 +67,7 @@ void MainOptHandler::accountOptHandler(std::string account) {
{"description", no_argument, nullptr, 'D'}, {"description", no_argument, nullptr, 'D'},
}; };
auto acctOperation = std::make_unique<AccountOperation>(account); auto acctOperation = std::make_unique<AccountOperation>(db, account);
while (true) { while (true) {
int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:dFvD", accountLongOpts, nullptr); int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:dFvD", accountLongOpts, nullptr);
@ -75,7 +77,7 @@ void MainOptHandler::accountOptHandler(std::string account) {
switch (opt) { switch (opt) {
case 'h': case 'h':
help(); help();
exit(0); throw Budget::Exceptions::HelpRequested("Help requested at account");
case 'a': case 'a':
case 'c': case 'c':
case 'e': case 'e':
@ -98,7 +100,7 @@ void MainOptHandler::accountOptHandler(std::string account) {
break; break;
case '?': case '?':
help(); help();
exit(0); throw Budget::Exceptions::HelpRequested("Help requested at account, unknown argument.");
default: default:
break; break;
} }
@ -117,7 +119,7 @@ void MainOptHandler::createOptHandler(std::string account) {
{"description", required_argument, nullptr, 'd'}, {"description", required_argument, nullptr, 'd'},
}; };
auto createOperation = std::make_unique<CreateOperation>(account); auto createOperation = std::make_unique<CreateOperation>(db, account);
while (true) { while (true) {
int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:d:", createLongOpts, nullptr); int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:d:", createLongOpts, nullptr);
@ -127,7 +129,7 @@ void MainOptHandler::createOptHandler(std::string account) {
switch (opt) { switch (opt) {
case 'h': case 'h':
help(); help();
exit(0); throw Budget::Exceptions::HelpRequested("Help requested at create");
case 'a': case 'a':
case 'c': case 'c':
case 'e': case 'e':
@ -140,7 +142,7 @@ void MainOptHandler::createOptHandler(std::string account) {
break; break;
case '?': case '?':
help(); help();
exit(0); throw Budget::Exceptions::HelpRequested("Help requested at create, unknown argument.");
default: default:
break; break;
} }
@ -162,7 +164,7 @@ void MainOptHandler::earnOptHandler(std::string account) {
{"date", required_argument, nullptr, 'D'}, {"date", required_argument, nullptr, 'D'},
}; };
auto earnOperation = std::make_unique<EarnOperation>(account); auto earnOperation = std::make_unique<EarnOperation>(db, account);
while (true) { while (true) {
int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:v:d:r:D:", earnLongOpts, nullptr); int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:v:d:r:D:", earnLongOpts, nullptr);
@ -172,7 +174,7 @@ void MainOptHandler::earnOptHandler(std::string account) {
switch (opt) { switch (opt) {
case 'h': case 'h':
help(); help();
exit(0); throw Budget::Exceptions::HelpRequested("Help requested at earn");
case 'a': case 'a':
case 'c': case 'c':
case 'e': case 'e':
@ -186,7 +188,7 @@ void MainOptHandler::earnOptHandler(std::string account) {
} catch (std::exception const &e) { } catch (std::exception const &e) {
help(); help();
std::cout << "Bad value value" << std::endl; std::cout << "Bad value value" << std::endl;
exit(1); throw Budget::Exceptions::BadValue("Bad value, cannot parse to decimal.");
} }
break; break;
} }
@ -203,7 +205,7 @@ void MainOptHandler::earnOptHandler(std::string account) {
if (strptime(optarg, "%m/%d/%YT%H:%M:%S", &t) == nullptr) { if (strptime(optarg, "%m/%d/%YT%H:%M:%S", &t) == nullptr) {
help(); help();
std::cout << "Bad time value" << std::endl; std::cout << "Bad time value" << std::endl;
exit(1); throw Budget::Exceptions::BadValue("Bad Value, cannot parse to int.");
} }
ts = mktime(&t); ts = mktime(&t);
earnOperation->flags.date = (long long) ts; earnOperation->flags.date = (long long) ts;
@ -211,7 +213,7 @@ void MainOptHandler::earnOptHandler(std::string account) {
} }
case '?': case '?':
help(); help();
exit(0); throw Budget::Exceptions::HelpRequested("Help requested at earn, unknown argument.");
default: default:
break; break;
} }
@ -233,7 +235,7 @@ void MainOptHandler::paymentOptHandler(std::string account) {
{"date", required_argument, nullptr, 'D'}, {"date", required_argument, nullptr, 'D'},
}; };
auto payOperation = std::make_unique<PaymentOperation>(account); auto payOperation = std::make_unique<PaymentOperation>(db, account);
while (true) { while (true) {
int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:v:d:r:D", paymentLongOpts, nullptr); int opt = getopt_long(argv.size(), argv.data(), "ha:c:e:p:v:d:r:D", paymentLongOpts, nullptr);
@ -243,7 +245,7 @@ void MainOptHandler::paymentOptHandler(std::string account) {
switch (opt) { switch (opt) {
case 'h': case 'h':
help(); help();
exit(0); throw Budget::Exceptions::HelpRequested("Help requested at payment");
case 'a': case 'a':
case 'c': case 'c':
case 'e': case 'e':
@ -257,7 +259,7 @@ void MainOptHandler::paymentOptHandler(std::string account) {
} catch (std::exception const &e) { } catch (std::exception const &e) {
help(); help();
std::cout << "Bad value value" << std::endl; std::cout << "Bad value value" << std::endl;
exit(1); throw Budget::Exceptions::BadValue("Bad value, cannot parse to decimal.");
} }
break; break;
} }
@ -274,7 +276,7 @@ void MainOptHandler::paymentOptHandler(std::string account) {
if (strptime(optarg, "%m/%d/%YT%H:%M:%S", &t) == nullptr) { if (strptime(optarg, "%m/%d/%YT%H:%M:%S", &t) == nullptr) {
help(); help();
std::cout << "Bad time value" << std::endl; std::cout << "Bad time value" << std::endl;
exit(1); throw Budget::Exceptions::BadValue("Bad value, time invalid.");
} }
ts = mktime(&t); ts = mktime(&t);
payOperation->flags.date = (long long) ts; payOperation->flags.date = (long long) ts;
@ -282,7 +284,7 @@ void MainOptHandler::paymentOptHandler(std::string account) {
} }
case '?': case '?':
help(); help();
exit(0); throw Budget::Exceptions::HelpRequested("Help requested at payment");
default: default:
break; break;
} }

View File

@ -14,7 +14,7 @@
namespace Budget::OptHandlers { namespace Budget::OptHandlers {
class MainOptHandler { class MainOptHandler {
public: public:
explicit MainOptHandler(const std::vector<char *> &argv); explicit MainOptHandler(const std::vector<char *> &argv, sqlite3 *pSqlite3);
void help(); void help();
@ -30,6 +30,8 @@ namespace Budget::OptHandlers {
void paymentOptHandler(std::string account); void paymentOptHandler(std::string account);
const std::vector<char *> &argv; const std::vector<char *> &argv;
sqlite3 *db;
}; };
} }

View File

@ -3,3 +3,5 @@
// //
#include "operation.h" #include "operation.h"
Budget::OptHandlers::Operation::Operation(sqlite3 *db) : db(db) {}

View File

@ -5,13 +5,20 @@
#ifndef BUDGET_OPERATION_H #ifndef BUDGET_OPERATION_H
#define BUDGET_OPERATION_H #define BUDGET_OPERATION_H
#include <sqlite3.h>
namespace Budget::OptHandlers { namespace Budget::OptHandlers {
class Operation { class Operation {
public: public:
explicit Operation(sqlite3 *db);
virtual void commit() = 0; virtual void commit() = 0;
struct Flags { struct Flags {
}; };
protected:
sqlite3 *db{};
}; };
} }