store sales
This commit is contained in:
parent
1ce329b99b
commit
bc67018c1c
8 changed files with 196 additions and 7 deletions
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
|
@ -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,
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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};
|
||||||
|
|
|
@ -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());
|
||||||
|
|
|
@ -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,12 +43,23 @@ 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(); });
|
||||||
if (iter == articles_.end())
|
if (iter == articles_.end())
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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>
|
||||||
|
|
Loading…
Reference in a new issue