store sales

This commit is contained in:
Martin Brodbeck 2018-07-25 09:31:17 +02:00
parent 1ce329b99b
commit bc67018c1c
8 changed files with 196 additions and 7 deletions

View file

@ -63,7 +63,8 @@
"algorithm": "cpp", "algorithm": "cpp",
"cinttypes": "cpp", "cinttypes": "cpp",
"condition_variable": "cpp", "condition_variable": "cpp",
"mutex": "cpp" "mutex": "cpp",
"hash_map": "cpp"
}, },
"C_Cpp.clang_format_path": "/usr/bin/clang-format", "C_Cpp.clang_format_path": "/usr/bin/clang-format",
"cmake.configureOnOpen": true, "cmake.configureOnOpen": true,

View file

@ -402,6 +402,106 @@ unsigned int Database::storeArticles(std::vector<Article*> articles)
return count; return count;
} }
unsigned int Database::storeSales(std::vector<std::unique_ptr<Sale>>& 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<std::unique_ptr<Seller>>& sellers) unsigned int Database::loadSellers(std::vector<std::unique_ptr<Seller>>& sellers)
{ {
int retCode{}; int retCode{};
@ -471,3 +571,68 @@ unsigned int Database::loadSellers(std::vector<std::unique_ptr<Seller>>& sellers
return count; return count;
} }
unsigned int Database::loadSales(std::vector<std::unique_ptr<Sale>>& sales,
std::vector<std::unique_ptr<Seller>>& 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>();
sale->setUuidFromString(reinterpret_cast<const char*>(sqlite3_column_text(stmt, 0)));
sale->setSourceNo(sqlite3_column_int(stmt, 1));
sale->setTimestamp(reinterpret_cast<const char*>(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<const char*>(sqlite3_column_text(stmt, 1)));
if (article != nullptr) {
sale->addArticle(article);
break;
}
}
retCode = sqlite3_step(stmt);
}
sqlite3_finalize(stmt);
}
return count;
}

View file

@ -1,6 +1,7 @@
#ifndef DATABASE_H #ifndef DATABASE_H
#define DATABASE_H #define DATABASE_H
#include "sale.h"
#include "seller.h" #include "seller.h"
#include <string> #include <string>
@ -16,8 +17,12 @@ class Database
Database(const Database&) = delete; Database(const Database&) = delete;
Database& operator=(const Database&) = delete; Database& operator=(const Database&) = delete;
void exec(const std::string& sql); void exec(const std::string& sql);
unsigned int storeSellers(std::vector<std::unique_ptr<Seller>>& sellers, bool onlyDelete = false); unsigned int storeSellers(std::vector<std::unique_ptr<Seller>>& sellers,
bool onlyDelete = false);
unsigned int loadSellers(std::vector<std::unique_ptr<Seller>>& sellers); unsigned int loadSellers(std::vector<std::unique_ptr<Seller>>& sellers);
unsigned int storeSales(std::vector<std::unique_ptr<Sale>>& sales);
unsigned int loadSales(std::vector<std::unique_ptr<Sale>>& sales,
std::vector<std::unique_ptr<Seller>>& sellers);
private: private:
sqlite3* db_{nullptr}; sqlite3* db_{nullptr};

View file

@ -17,12 +17,14 @@ void Marketplace::storeToDb(bool onlyDelete)
{ {
Database db; Database db;
db.storeSellers(sellers_, onlyDelete); db.storeSellers(sellers_, onlyDelete);
db.storeSales(sales_);
} }
void Marketplace::loadFromDb() void Marketplace::loadFromDb()
{ {
Database db; Database db;
db.loadSellers(sellers_); db.loadSellers(sellers_);
db.loadSales(sales_, sellers_);
} }
SellersVec& Marketplace::getSellers() { return sellers_; } SellersVec& Marketplace::getSellers() { return sellers_; }
@ -91,6 +93,7 @@ void Marketplace::finishCurrentSale()
return; return;
auto sale = std::make_unique<Sale>(); auto sale = std::make_unique<Sale>();
sale->createUuid();
for (auto iter = basket_.begin(); iter != basket_.end(); ++iter) { for (auto iter = basket_.begin(); iter != basket_.end(); ++iter) {
sale->addArticle((*iter).get()); sale->addArticle((*iter).get());

View file

@ -1,7 +1,8 @@
#include "seller.h" #include "seller.h"
Seller::Seller(const std::string& firstName, const std::string& lastName, int sellerNo, Seller::Seller(const std::string& firstName, const std::string& lastName, int sellerNo,
int numArticlesOffered) : Entity() int numArticlesOffered)
: Entity()
{ {
firstName_ = firstName; firstName_ = firstName;
lastName_ = lastName; lastName_ = lastName;
@ -42,11 +43,22 @@ std::vector<Article*> Seller::getArticles(bool onlySold) const
return articles; 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<int>(getArticles(true).size()); } int Seller::numArticlesSold() const { return static_cast<int>(getArticles(true).size()); }
int Seller::numArticlesOffered() const { return numArticlesOffered_; } int Seller::numArticlesOffered() const { return numArticlesOffered_; }
int Seller::getMaxArticleNo() const{ int Seller::getMaxArticleNo() const
{
auto iter = std::max_element( auto iter = std::max_element(
articles_.begin(), articles_.end(), articles_.begin(), articles_.end(),
[](const auto& a, const auto& b) -> bool { return a->getArticleNo() < b->getArticleNo(); }); [](const auto& a, const auto& b) -> bool { return a->getArticleNo() < b->getArticleNo(); });

View file

@ -32,6 +32,7 @@ class Seller : public Entity
int numArticlesSold() const; int numArticlesSold() const;
// int numArticlesTotal() const; // int numArticlesTotal() const;
std::vector<Article*> getArticles(bool onlySold = true) const; std::vector<Article*> getArticles(bool onlySold = true) const;
Article* getArticleByUuid(const std::string& uuidString);
int getMaxArticleNo() const; int getMaxArticleNo() const;
friend bool operator<(const Seller& li, const Seller& re); friend bool operator<(const Seller& li, const Seller& re);

View file

@ -90,6 +90,8 @@ void MainWindow::on_sellerNoEdit_checkSellerNo()
if (dialogResult == QDialog::Accepted) { if (dialogResult == QDialog::Accepted) {
int price = priceDialog.getPrice(); int price = priceDialog.getPrice();
dynamic_cast<BasketModel*>(ui_.basketView->model())->addArticle(seller, price); dynamic_cast<BasketModel*>(ui_.basketView->model())->addArticle(seller, price);
std::string sumStr = "Gesamt: " + marketplace_->getBasketSumAsString();
ui_.basketSumLabel->setText(sumStr.c_str());
} }
} }

View file

@ -30,7 +30,7 @@
</widget> </widget>
</item> </item>
<item> <item>
<widget class="QLabel" name="label_10"> <widget class="QLabel" name="basketSumLabel">
<property name="font"> <property name="font">
<font> <font>
<pointsize>18</pointsize> <pointsize>18</pointsize>
@ -42,7 +42,7 @@
<enum>QFrame::Box</enum> <enum>QFrame::Box</enum>
</property> </property>
<property name="text"> <property name="text">
<string>Gesamt: -,--</string> <string>Gesamt: ---</string>
</property> </property>
<property name="alignment"> <property name="alignment">
<set>Qt::AlignCenter</set> <set>Qt::AlignCenter</set>