diff --git a/.vscode/settings.json b/.vscode/settings.json index cd0c2ad..ae7faf9 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -63,7 +63,8 @@ "algorithm": "cpp", "cinttypes": "cpp", "condition_variable": "cpp", - "mutex": "cpp" + "mutex": "cpp", + "hash_map": "cpp" }, "C_Cpp.clang_format_path": "/usr/bin/clang-format", "cmake.configureOnOpen": true, diff --git a/src/core/database.cpp b/src/core/database.cpp index 524fabd..473258e 100644 --- a/src/core/database.cpp +++ b/src/core/database.cpp @@ -402,6 +402,106 @@ unsigned int Database::storeArticles(std::vector articles) return count; } +unsigned int Database::storeSales(std::vector>& sales) +{ + int retCode{}; + int count{}; + sqlite3_stmt* stmt; + + if (sales.size() == 0) + return 0; + + beginTransaction(); + + for (auto& sale : sales) { + if (sale->getState() == Sale::State::NEW) { + retCode = sqlite3_prepare_v2(db_, + "INSERT INTO sales" + " (id, source_no, sold_at)" + " VALUES (:uuid, :source_no, :sold_at)", + -1, &stmt, nullptr); + + if (retCode != SQLITE_OK) + throw std::runtime_error(sqlite3_errmsg(db_)); + + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":uuid"), + boost::uuids::to_string(sale->getUuid()).c_str(), -1, + SQLITE_TRANSIENT); + sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":source_no"), + sale->getSourceNo()); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":sold_at"), + sale->getTimestamp().c_str(), -1, SQLITE_TRANSIENT); + + retCode = sqlite3_step(stmt); + + if (retCode != SQLITE_DONE) { + + std::string errMsg(sqlite3_errmsg(db_)); + sqlite3_finalize(stmt); + throw std::runtime_error(errMsg); + } + ++count; + sqlite3_finalize(stmt); + + for (const auto& article : sale->getArticles()) { + retCode = sqlite3_prepare_v2(db_, + "INSERT INTO sales_items" + " (sale_id, article_id)" + " VALUES (:sale_id, :article_id)", + -1, &stmt, nullptr); + + if (retCode != SQLITE_OK) + throw std::runtime_error(sqlite3_errmsg(db_)); + + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":sale_id"), + sale->getUuidAsString().c_str(), -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":article_id"), + article->getUuidAsString().c_str(), -1, SQLITE_TRANSIENT); + + retCode = sqlite3_step(stmt); + + if (retCode != SQLITE_DONE) { + + std::string errMsg(sqlite3_errmsg(db_)); + sqlite3_finalize(stmt); + throw std::runtime_error(errMsg); + } + sqlite3_finalize(stmt); + } + } else if (sale->getState() == Sale::State::DELETE) { + retCode = + sqlite3_prepare_v2(db_, "DELETE FROM sales WHERE id = :uuid", -1, &stmt, nullptr); + + if (retCode != SQLITE_OK) + throw std::runtime_error(sqlite3_errmsg(db_)); + + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":uuid"), + sale->getUuidAsString().c_str(), -1, SQLITE_TRANSIENT); + + retCode = sqlite3_step(stmt); + + if (retCode != SQLITE_DONE) { + + std::string errMsg(sqlite3_errmsg(db_)); + sqlite3_finalize(stmt); + throw std::runtime_error(errMsg); + } + ++count; + sqlite3_finalize(stmt); + } + + // Maybe not necessary (because of DELETE CASCADE): Delete here individual articles + } + + endTransaction(); + + for (auto& sale : sales) { + sale->setState(Sale::State::OK); + } + + return count; +} + unsigned int Database::loadSellers(std::vector>& sellers) { int retCode{}; @@ -469,5 +569,70 @@ unsigned int Database::loadSellers(std::vector>& sellers sqlite3_finalize(stmt); } + return count; +} + +unsigned int Database::loadSales(std::vector>& sales, + std::vector>& sellers) +{ + int retCode{}; + int count{}; + sqlite3_stmt* stmt; + + retCode = sqlite3_prepare_v2(db_, + "SELECT id, source_no, sold_at" + " FROM sales ORDER BY sold_at", + -1, &stmt, nullptr); + if (retCode != SQLITE_OK) + throw std::runtime_error(sqlite3_errmsg(db_)); + + retCode = sqlite3_step(stmt); + + sales.clear(); + + while (retCode != SQLITE_DONE) { + ++count; + auto sale = std::make_unique(); + sale->setUuidFromString(reinterpret_cast(sqlite3_column_text(stmt, 0))); + sale->setSourceNo(sqlite3_column_int(stmt, 1)); + sale->setTimestamp(reinterpret_cast(sqlite3_column_text(stmt, 2))); + sale->setState(Sale::State::OK); + sales.push_back(std::move(sale)); + + retCode = sqlite3_step(stmt); + } + + sqlite3_finalize(stmt); + + for (auto& sale : sales) { + retCode = sqlite3_prepare_v2(db_, + "SELECT sale_id, article_id" + " FROM sales_items" + " WHERE sale_id = :sale_uuid", + -1, &stmt, nullptr); + if (retCode != SQLITE_OK) + throw std::runtime_error(sqlite3_errmsg(db_)); + + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":sale_uuid"), + sale->getUuidAsString().c_str(), -1, SQLITE_TRANSIENT); + + retCode = sqlite3_step(stmt); + + while (retCode != SQLITE_DONE) { + for (auto& seller : sellers) { + auto article = seller->getArticleByUuid( + reinterpret_cast(sqlite3_column_text(stmt, 1))); + if (article != nullptr) { + sale->addArticle(article); + break; + } + } + + retCode = sqlite3_step(stmt); + } + + sqlite3_finalize(stmt); + } + return count; } \ No newline at end of file diff --git a/src/core/database.h b/src/core/database.h index baf03ac..4515d88 100644 --- a/src/core/database.h +++ b/src/core/database.h @@ -1,6 +1,7 @@ #ifndef DATABASE_H #define DATABASE_H +#include "sale.h" #include "seller.h" #include @@ -16,8 +17,12 @@ class Database Database(const Database&) = delete; Database& operator=(const Database&) = delete; void exec(const std::string& sql); - unsigned int storeSellers(std::vector>& sellers, bool onlyDelete = false); + unsigned int storeSellers(std::vector>& sellers, + bool onlyDelete = false); unsigned int loadSellers(std::vector>& sellers); + unsigned int storeSales(std::vector>& sales); + unsigned int loadSales(std::vector>& sales, + std::vector>& sellers); private: sqlite3* db_{nullptr}; diff --git a/src/core/marketplace.cpp b/src/core/marketplace.cpp index 55ab5c6..8bc45ec 100644 --- a/src/core/marketplace.cpp +++ b/src/core/marketplace.cpp @@ -17,12 +17,14 @@ void Marketplace::storeToDb(bool onlyDelete) { Database db; db.storeSellers(sellers_, onlyDelete); + db.storeSales(sales_); } void Marketplace::loadFromDb() { Database db; db.loadSellers(sellers_); + db.loadSales(sales_, sellers_); } SellersVec& Marketplace::getSellers() { return sellers_; } @@ -91,6 +93,7 @@ void Marketplace::finishCurrentSale() return; auto sale = std::make_unique(); + sale->createUuid(); for (auto iter = basket_.begin(); iter != basket_.end(); ++iter) { sale->addArticle((*iter).get()); diff --git a/src/core/seller.cpp b/src/core/seller.cpp index 97b5f82..82aaa6b 100644 --- a/src/core/seller.cpp +++ b/src/core/seller.cpp @@ -1,7 +1,8 @@ #include "seller.h" Seller::Seller(const std::string& firstName, const std::string& lastName, int sellerNo, - int numArticlesOffered) : Entity() + int numArticlesOffered) + : Entity() { firstName_ = firstName; lastName_ = lastName; @@ -42,12 +43,23 @@ std::vector Seller::getArticles(bool onlySold) const return articles; } +Article* Seller::getArticleByUuid(const std::string& uuidString) +{ + auto iter = std::find_if(articles_.begin(), articles_.end(), [&uuidString](const auto& art) { + return art->getUuidAsString() == uuidString; + }); + if (iter == articles_.end()) + return nullptr; + return (*iter).get(); +} + int Seller::numArticlesSold() const { return static_cast(getArticles(true).size()); } int Seller::numArticlesOffered() const { return numArticlesOffered_; } -int Seller::getMaxArticleNo() const{ - auto iter = std::max_element( +int Seller::getMaxArticleNo() const +{ + auto iter = std::max_element( articles_.begin(), articles_.end(), [](const auto& a, const auto& b) -> bool { return a->getArticleNo() < b->getArticleNo(); }); if (iter == articles_.end()) diff --git a/src/core/seller.h b/src/core/seller.h index c2ab2a7..c51bccb 100644 --- a/src/core/seller.h +++ b/src/core/seller.h @@ -32,6 +32,7 @@ class Seller : public Entity int numArticlesSold() const; // int numArticlesTotal() const; std::vector getArticles(bool onlySold = true) const; + Article* getArticleByUuid(const std::string& uuidString); int getMaxArticleNo() const; friend bool operator<(const Seller& li, const Seller& re); diff --git a/src/gui/mainwindow.cpp b/src/gui/mainwindow.cpp index 1a4df3e..08f8e4d 100644 --- a/src/gui/mainwindow.cpp +++ b/src/gui/mainwindow.cpp @@ -90,6 +90,8 @@ void MainWindow::on_sellerNoEdit_checkSellerNo() if (dialogResult == QDialog::Accepted) { int price = priceDialog.getPrice(); dynamic_cast(ui_.basketView->model())->addArticle(seller, price); + std::string sumStr = "Gesamt: " + marketplace_->getBasketSumAsString(); + ui_.basketSumLabel->setText(sumStr.c_str()); } } diff --git a/src/gui/mainwindow.ui b/src/gui/mainwindow.ui index 6491372..5d32ee6 100644 --- a/src/gui/mainwindow.ui +++ b/src/gui/mainwindow.ui @@ -30,7 +30,7 @@ - + 18 @@ -42,7 +42,7 @@ QFrame::Box - Gesamt: -,-- € + Gesamt: --- Qt::AlignCenter