diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index e238864..78113b5 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -14,6 +14,7 @@ set(CORE_SOURCES seller.cpp article.cpp sale.cpp + marketplace.cpp ) add_library(core STATIC ${CORE_SOURCES}) diff --git a/src/core/article.cpp b/src/core/article.cpp index 74c00d9..42050e0 100644 --- a/src/core/article.cpp +++ b/src/core/article.cpp @@ -20,4 +20,8 @@ std::string Article::getDescription() { return description_; } Seller* Article::getSeller() { return sellerPtr_; } -int Article::getPrice() { return price_; } \ No newline at end of file +int Article::getPrice() { return price_; } + +int Article::getArticleNo() { + return articleNo_; +} \ No newline at end of file diff --git a/src/core/article.h b/src/core/article.h index 5c78b80..a9ba3b8 100644 --- a/src/core/article.h +++ b/src/core/article.h @@ -24,6 +24,7 @@ class Article : public Entity //void setSeller(std::shared_ptr sellerPtr); void setSeller(Seller* sellerPtr); + int getArticleNo(); std::string getDescription(); Seller* getSeller(); int getPrice(); diff --git a/src/core/database.cpp b/src/core/database.cpp index 43c82c3..e7b4168 100644 --- a/src/core/database.cpp +++ b/src/core/database.cpp @@ -145,7 +145,7 @@ void Database::beginTransaction() { exec("BEGIN TRANSACTION"); } void Database::endTransaction() { exec("END TRANSACTION"); } -unsigned int Database::storeSellers(std::vector& sellers) +unsigned int Database::storeSellers(std::vector>& sellers) { int retCode{}; int count{}; @@ -154,7 +154,7 @@ unsigned int Database::storeSellers(std::vector& sellers) beginTransaction(); for (auto& seller : sellers) { - if (seller.getState() == Entity::State::NEW) { + if (seller->getState() == Seller::State::NEW) { retCode = sqlite3_prepare_v2( db_, "INSERT INTO sellers" @@ -165,16 +165,17 @@ unsigned int Database::storeSellers(std::vector& sellers) 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(seller.getUuid()).c_str(), -1, nullptr); + int test = sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":uuid"), + boost::uuids::to_string(seller->getUuid()).c_str(), -1, SQLITE_TRANSIENT); + std::cout << "!!! TEST: " << test << "\n"; sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":seller_no"), - seller.getSellerNo()); + seller->getSellerNo()); sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":first_name"), - seller.getFirstName().c_str(), -1, nullptr); + seller->getFirstName().c_str(), -1, SQLITE_TRANSIENT); sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":last_name"), - seller.getLastName().c_str(), -1, nullptr); + seller->getLastName().c_str(), -1, SQLITE_TRANSIENT); sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":num_offered_articles"), - seller.numArticlesOffered()); + seller->numArticlesOffered()); retCode = sqlite3_step(stmt); @@ -184,12 +185,103 @@ unsigned int Database::storeSellers(std::vector& sellers) sqlite3_finalize(stmt); throw std::runtime_error(errMsg); } - seller.setState(Seller::State::OK); + seller->setState(Seller::State::OK); ++count; sqlite3_finalize(stmt); + } else if (seller->getState() == Seller::State::UPDATE) { + // TODO + retCode = sqlite3_prepare_v2( + db_, + "UPDATE sellers SET" + " seller_no = :seller_no, first_name = :first_name," + " last_name = :last_name, num_offered_articles = :num_offered_articles" + " 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"), + boost::uuids::to_string(seller->getUuid()).c_str(), -1, SQLITE_TRANSIENT); + sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":seller_no"), + seller->getSellerNo()); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":first_name"), + seller->getFirstName().c_str(), -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":last_name"), + seller->getLastName().c_str(), -1, SQLITE_TRANSIENT); + sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":num_offered_articles"), + seller->numArticlesOffered()); + + retCode = sqlite3_step(stmt); + + if (retCode != SQLITE_DONE) { + + std::string errMsg(sqlite3_errmsg(db_)); + sqlite3_finalize(stmt); + throw std::runtime_error(errMsg); + } + seller->setState(Seller::State::OK); + ++count; + sqlite3_finalize(stmt); + } else if (seller->getState() == Seller::State::DELETE) { + count += static_cast(seller->getArticles(false).size()); + // TODO + } + + if (seller->getState() != Seller::State::DELETE) { + count += storeArticles(stmt, seller->getArticles(false)); } } endTransaction(); + return count; +} + +unsigned int Database::storeArticles(sqlite3_stmt* stmt, std::vector articles) +{ + int retCode{}; + int count{}; + + for (auto& article : articles) { + if (article->getState() == Article::State::NEW) { + retCode = sqlite3_prepare_v2( + db_, + "INSERT INTO articles" + " (id, seller_id, source_no, article_no, description, price)" + " VALUES (:uuid, :seller_id, :source_no, :article_no, :desc, :price)", + -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(article->getUuid()).c_str(), -1, SQLITE_TRANSIENT); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":seller_id"), + boost::uuids::to_string(article->getSeller()->getUuid()).c_str(), -1, + SQLITE_TRANSIENT); + sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":source_no"), + article->getSourceNo()); + sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":article_no"), + article->getArticleNo()); + sqlite3_bind_text(stmt, sqlite3_bind_parameter_index(stmt, ":desctiption"), + article->getDescription().c_str(), -1, SQLITE_TRANSIENT); + sqlite3_bind_int(stmt, sqlite3_bind_parameter_index(stmt, ":price"), + article->getPrice()); + + retCode = sqlite3_step(stmt); + + if (retCode != SQLITE_DONE) { + + std::string errMsg(sqlite3_errmsg(db_)); + sqlite3_finalize(stmt); + throw std::runtime_error(errMsg); + } + article->setState(Seller::State::OK); + ++count; + sqlite3_finalize(stmt); + } else if (article->getState() == Article::State::UPDATE) { + } + } + return count; } \ No newline at end of file diff --git a/src/core/database.h b/src/core/database.h index 83fe27c..447fdb4 100644 --- a/src/core/database.h +++ b/src/core/database.h @@ -9,21 +9,23 @@ class Database { -public: + public: Database(const std::string& dbname); ~Database(); Database(const Database&) = delete; Database& operator=(const Database&) = delete; void exec(const std::string& sql); void init(); - unsigned int storeSellers(std::vector& sellers); -private: - sqlite3 *db_; + unsigned int storeSellers(std::vector>& sellers); + + private: + sqlite3* db_; std::string dbname_; void beginTransaction(); void endTransaction(); void createNew(); int getVersion(); + unsigned int storeArticles(sqlite3_stmt* stmt, std::vector articles); }; #endif // DATABASE_H \ No newline at end of file diff --git a/src/core/entity.cpp b/src/core/entity.cpp index 08614df..f203599 100644 --- a/src/core/entity.cpp +++ b/src/core/entity.cpp @@ -22,4 +22,12 @@ void Entity::setUuidFromString(const std::string& uuidString) inline Entity::State Entity::getState() const { return state_; +} + +void Entity::setSourceNo(int sourceNo) { + sourceNo_ = sourceNo; +} + +int Entity::getSourceNo() const { + return sourceNo_; } \ No newline at end of file diff --git a/src/core/entity.h b/src/core/entity.h index 11890c6..7c37fbf 100644 --- a/src/core/entity.h +++ b/src/core/entity.h @@ -12,15 +12,20 @@ class Entity enum class State { NEW, UPDATE, DELETE, OK }; virtual ~Entity() = 0; - const boost::uuids::uuid& getUuid() const { return uuid_; }; + void createUuid(); void setUuidFromString(const std::string& uuidString); - virtual State getState() const; void setState(State state) { state_ = state; } + void setSourceNo(int sourceNo); + + const boost::uuids::uuid& getUuid() const { return uuid_; }; + virtual State getState() const; + virtual int getSourceNo() const; private: boost::uuids::uuid uuid_{}; State state_{State::NEW}; + int sourceNo_{}; }; #endif // ENTITY_H \ No newline at end of file diff --git a/src/core/marketplace.cpp b/src/core/marketplace.cpp new file mode 100644 index 0000000..946e1ad --- /dev/null +++ b/src/core/marketplace.cpp @@ -0,0 +1,9 @@ +#include "marketplace.h" +#include "database.h" + +void Marketplace::storeToDb() { + const std::string DB_PATH{"/tmp/kima2.db"}; + + Database db(DB_PATH); + db.storeSellers(sellers_); +} \ No newline at end of file diff --git a/src/core/marketplace.h b/src/core/marketplace.h new file mode 100644 index 0000000..ba78564 --- /dev/null +++ b/src/core/marketplace.h @@ -0,0 +1,21 @@ +#ifndef MARKETPLACE_H +#define MARKETPLACE_H + +#include "article.h" +#include "sale.h" +#include "seller.h" + +#include + +class Marketplace +{ + public: + void storeToDb(); + void loadFromDb(); + private: + std::vector> sellers_; + //std::vector> articles_; + std::vector> sales_; +}; + +#endif \ No newline at end of file diff --git a/src/core/sale.cpp b/src/core/sale.cpp index 92b0140..1da00fc 100644 --- a/src/core/sale.cpp +++ b/src/core/sale.cpp @@ -8,9 +8,33 @@ void Sale::addArticle(std::shared_ptr
articlePtr) articles_.push_back(articlePtr); } +std::vector Sale::getArticles() +{ + std::vector articles(articles_.size()); + for (const auto& article : articles_) { + articles.push_back(article.get()); + } + + return articles; +} + +void Sale::removeArticle(const Article* articlePtr) +{ + auto it = std::find_if(articles_.begin(), articles_.end(), + [&articlePtr](auto art) { return art.get() == articlePtr; }); + if (it != articles_.end()) { + (*it)->setSale(nullptr); + articles_.erase(it); + } +} + int Sale::sumInCents() { int sum = std::accumulate(articles_.begin(), articles_.end(), 0, - [](int a, std::shared_ptr
b) { return a + b->getPrice(); }); + [](int a, std::shared_ptr
b) { return a + b->getPrice(); }); return sum; -} \ No newline at end of file +} + +std::string Sale::getTimestamp() { return timestamp_; } + +void Sale::setTimestamp(const std::string& timestamp) { timestamp_ = timestamp; } \ No newline at end of file diff --git a/src/core/sale.h b/src/core/sale.h index 11253bd..f11f14c 100644 --- a/src/core/sale.h +++ b/src/core/sale.h @@ -5,17 +5,25 @@ #include -#include +#include "boost/date_time/posix_time/posix_time.hpp" class Article; class Sale : public Entity { public: - int sumInCents(); void addArticle(std::shared_ptr
articlePtr); + void setTimestamp(const std::string& timestamp); + + std::vector getArticles(); + std::string getTimestamp(); + int sumInCents(); + + void removeArticle(const Article* articlePtr); + private: - boost::posix_time::ptime systemTime_{boost::posix_time::second_clock::local_time()}; + std::string timestamp_{ + boost::posix_time::to_iso_extended_string(boost::posix_time::second_clock::local_time())}; std::vector> articles_{}; }; diff --git a/test/test_database.cpp b/test/test_database.cpp index e4052c4..1493a10 100644 --- a/test/test_database.cpp +++ b/test/test_database.cpp @@ -17,23 +17,28 @@ BOOST_AUTO_TEST_CASE(store_seller_fail) { Database db(":memory:"); db.init(); - std::vector sellers; - sellers.push_back({}); - sellers.push_back({}); + std::vector> sellers; + sellers.push_back(std::make_shared()); + sellers.push_back(std::make_shared()); BOOST_CHECK_THROW(db.storeSellers(sellers), std::runtime_error); } BOOST_AUTO_TEST_CASE(store_sellers_succ) { Database db(":memory:"); db.init(); - std::vector sellers; - Seller a{}; - a.createUuid(); - a.setSellerNo(1); - Seller b{}; - b.createUuid(); - b.setSellerNo(2); - BOOST_TEST(a.getUuid() != b.getUuid()); + std::vector> sellers; + auto a = std::make_shared(); + a->createUuid(); + a->setSellerNo(1); + auto b = std::make_shared("Max", "Mustermann"); + b->createUuid(); + b->setSellerNo(2); + auto c = std::make_shared
(); + c->createUuid(); + c->setPrice(500); + c->setDescription("Test"); + b->addArticle(c); + BOOST_TEST(a->getUuid() != b->getUuid()); sellers.push_back(a); sellers.push_back(b); BOOST_CHECK_NO_THROW(db.storeSellers(sellers)); @@ -43,14 +48,14 @@ BOOST_AUTO_TEST_CASE(seller_states) { Database db(":memory:"); db.init(); - std::vector sellers; - Seller a; - a.setSellerNo(3); - a.createUuid(); + std::vector> sellers; + auto a = std::make_shared(); + a->setSellerNo(3); + a->createUuid(); sellers.push_back(a); std::cout << "Anzahl sellers: " << sellers.size() << "\n"; - BOOST_TEST((sellers.at(0).getState() == Entity::State::NEW)); + BOOST_TEST((sellers.at(0)->getState() == Entity::State::NEW)); BOOST_TEST(db.storeSellers(sellers) == 1); - BOOST_TEST((sellers.at(0).getState() == Entity::State::OK)); + BOOST_TEST((sellers.at(0)->getState() == Entity::State::OK)); BOOST_TEST(db.storeSellers(sellers) == 0); } \ No newline at end of file diff --git a/test/test_sale.cpp b/test/test_sale.cpp index 0ee1bed..7ef6bc4 100644 --- a/test/test_sale.cpp +++ b/test/test_sale.cpp @@ -30,4 +30,15 @@ BOOST_AUTO_TEST_CASE(articles_sum) BOOST_TEST(sale.sumInCents() == 550); BOOST_TEST(seller.getArticles(true).size() == 10); +} + +BOOST_AUTO_TEST_CASE(remove_article) { + auto art = std::make_shared
(); + Sale sale{}; + + BOOST_TEST(art->isSold() == false); + sale.addArticle(art); + BOOST_TEST(art->isSold() == true); + sale.removeArticle(art.get()); + BOOST_TEST(art->isSold() == false); } \ No newline at end of file