KIMA2 ist ein kleines Kassenprogramm für Kindersachenmärkte.
https://www.rustysoft.de/?01_kima2
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
269 lines
7.9 KiB
269 lines
7.9 KiB
#include "marketplace.h" |
|
#include "database.h" |
|
#include "utils.h" |
|
|
|
#include <algorithm> |
|
#include <fstream> |
|
#include <iomanip> |
|
#include <numeric> |
|
#include <sstream> |
|
|
|
Marketplace::Marketplace() |
|
{ |
|
auto seller = std::make_unique<Seller>("Max", "Mustermann"); |
|
seller->createUuid(); |
|
sellers_.push_back(std::move(seller)); |
|
} |
|
|
|
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_; } |
|
|
|
SalesVec& Marketplace::getSales() { return sales_; } |
|
|
|
int Marketplace::getNextSellerNo() |
|
{ |
|
auto iter = std::max_element( |
|
sellers_.begin(), sellers_.end(), |
|
[](const auto& a, const auto& b) -> bool { return a->getSellerNo() < b->getSellerNo(); }); |
|
if (iter == sellers_.end()) |
|
return 1; |
|
return (*iter)->getSellerNo() + 1; |
|
} |
|
|
|
int Marketplace::getNextArticleNo() |
|
{ |
|
int maxArtNoInDb{0}; |
|
int maxArtNoInBasket{0}; |
|
|
|
auto iter = std::max_element(sellers_.begin(), sellers_.end(), |
|
[](const auto& a, const auto& b) -> bool { |
|
return a->getMaxArticleNo() < b->getMaxArticleNo(); |
|
}); |
|
if (iter != sellers_.end()) |
|
maxArtNoInDb = (*iter)->getMaxArticleNo(); |
|
|
|
auto iter2 = |
|
std::max_element(basket_.begin(), basket_.end(), [](const auto& a, const auto& b) -> bool { |
|
return a->getArticleNo() < b->getArticleNo(); |
|
}); |
|
|
|
if (iter2 != basket_.end()) |
|
maxArtNoInBasket = (*iter2)->getArticleNo(); |
|
|
|
return maxArtNoInBasket > maxArtNoInDb ? maxArtNoInBasket + 1 : maxArtNoInDb + 1; |
|
} |
|
|
|
int Marketplace::getNumSellersDelete() |
|
{ |
|
int count = std::count_if(sellers_.begin(), sellers_.end(), |
|
[](const auto& a) { return a->getState() == Seller::State::DELETE; }); |
|
return count; |
|
} |
|
|
|
void Marketplace::sortSellers() { std::sort(sellers_.begin(), sellers_.end()); } |
|
|
|
Seller* Marketplace::findSellerWithSellerNo(int sellerNo) |
|
{ |
|
auto iter = std::find_if(sellers_.begin(), sellers_.end(), |
|
[sellerNo](const auto& a) { return a->getSellerNo() == sellerNo; }); |
|
if (iter == sellers_.end()) |
|
return nullptr; |
|
return (*iter).get(); |
|
} |
|
|
|
Seller* Marketplace::findSellerWithUuid(const std::string& uuid) |
|
{ |
|
auto iter = std::find_if(sellers_.begin(), sellers_.end(), |
|
[uuid](const auto& a) { return a->getUuidAsString() == uuid; }); |
|
if (iter == sellers_.end()) |
|
return nullptr; |
|
return (*iter).get(); |
|
} |
|
|
|
void Marketplace::addArticleToBasket(std::unique_ptr<Article> article) |
|
{ |
|
basket_.push_back(std::move(article)); |
|
} |
|
|
|
size_t Marketplace::basketSize() { return basket_.size(); } |
|
|
|
void Marketplace::finishCurrentSale(std::unique_ptr<Sale> sale) |
|
{ |
|
if (basket_.size() == 0) |
|
return; |
|
|
|
for (auto iter = basket_.begin(); iter != basket_.end(); ++iter) { |
|
iter->get()->setSourceNo(sale->getSourceNo()); // update source_no for article in the case |
|
// the user has changed it in the meanwhile |
|
sale->addArticle(iter->get()); |
|
(*iter)->getSeller()->addArticle(std::move(*iter)); |
|
} |
|
|
|
sales_.push_back(std::move(sale)); |
|
basket_.clear(); |
|
storeToDb(); |
|
} |
|
|
|
BasketVec& Marketplace::getBasket() { return basket_; } |
|
|
|
int Marketplace::getBasketSumInCent() |
|
{ |
|
int sum = std::accumulate(basket_.begin(), basket_.end(), 0, |
|
[](int a, const auto& b) { return a + b->getPrice(); }); |
|
return sum; |
|
} |
|
|
|
std::string Marketplace::getBasketSumAsString() |
|
{ |
|
int sumInCent = getBasketSumInCent(); |
|
|
|
return formatCentAsEuroString(sumInCent); |
|
} |
|
|
|
void Marketplace::removeSale(boost::uuids::uuid uuid) |
|
{ |
|
sales_.erase(std::remove_if(sales_.begin(), sales_.end(), |
|
[&uuid](const auto& a) { return a->getUuid() == uuid; }), |
|
sales_.end()); |
|
} |
|
|
|
void Marketplace::setSalesToDelete(int cashPointNo) |
|
{ |
|
std::for_each(sales_.begin(), sales_.end(), [cashPointNo](auto& sale) { |
|
if (sale->getSourceNo() == cashPointNo) { |
|
sale->setState(Sale::State::DELETE); |
|
for (auto& article : sale->getArticles()) { |
|
article->setState(Article::State::DELETE); |
|
} |
|
} |
|
}); |
|
} |
|
|
|
void Marketplace::exportReportToCSV(const std::string& filename, int feeInPercent, int maxFeeInEuro) |
|
{ |
|
const char delimiter = ','; |
|
std::ofstream file(filename); |
|
|
|
file << "Verk.Nr." << delimiter << "Nachname" << delimiter << "Vorname" << delimiter |
|
<< "Anz. gemeldet" << delimiter << "Anz. verkauft" << delimiter << "Umsatz" << delimiter |
|
<< "Auszahlung\n"; |
|
|
|
for (const auto& seller : sellers_) { |
|
file << seller->getSellerNo() << delimiter |
|
<< escapeCsvValue(seller->getLastName(), delimiter) << delimiter |
|
<< escapeCsvValue(seller->getFirstName(), delimiter) << delimiter |
|
<< seller->numArticlesOffered() << delimiter << seller->numArticlesSold() << delimiter |
|
<< escapeCsvValue(seller->sumAsString(), delimiter) << delimiter |
|
<< escapeCsvValue(paymentAsString(seller->sumInCents(), feeInPercent, maxFeeInEuro), |
|
delimiter) |
|
<< "\n"; |
|
} |
|
} |
|
|
|
int Marketplace::getOverallSumInCent() |
|
{ |
|
int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, |
|
[](int a, const auto& b) { return a + b->sumInCents(); }); |
|
return sum; |
|
} |
|
|
|
std::string Marketplace::getOverallSumAsString() |
|
{ |
|
int sum = getOverallSumInCent(); |
|
return formatCentAsEuroString(sum); |
|
} |
|
|
|
int Marketplace::getOverallPaymentInCent(int percent, int maxFee) |
|
{ |
|
int sum = std::accumulate( |
|
sellers_.begin(), sellers_.end(), 0, [percent, maxFee](int a, const auto& b) { |
|
return a + b->sumInCents() - marketFee(b->sumInCents(), percent, maxFee); |
|
}); |
|
return sum; |
|
} |
|
|
|
std::string Marketplace::getOverallPaymentAsString(int percent, int maxFee) |
|
{ |
|
int sum = getOverallPaymentInCent(percent, maxFee); |
|
return formatCentAsEuroString(sum); |
|
} |
|
|
|
std::string Marketplace::getOverallRevenueAsString(int percent, int maxFee) |
|
{ |
|
int sum = getOverallSumInCent(); |
|
int pay = getOverallPaymentInCent(percent, maxFee); |
|
return formatCentAsEuroString(sum - pay); |
|
} |
|
|
|
double marketFee(int sum, int percent, int maxFee) |
|
{ |
|
int fee = (sum * percent) / 100.0L; |
|
if (maxFee <= 0) { |
|
return fee; |
|
} |
|
return fee > maxFee ? maxFee : fee; |
|
} |
|
|
|
std::string marketFeeAsString(int sum, int percent, int maxFee) |
|
{ |
|
return formatCentAsEuroString(marketFee(sum, percent, maxFee)); |
|
} |
|
|
|
std::string paymentAsString(int sumInCent, int percent, int maxFeeInCent) |
|
{ |
|
return formatCentAsEuroString(sumInCent - marketFee(sumInCent, percent, maxFeeInCent)); |
|
} |
|
|
|
std::string escapeCsvValue(const std::string& value, const char delimiter) |
|
{ |
|
std::stringstream output; |
|
bool containsDelim{false}; |
|
|
|
if (value.find(delimiter) != std::string::npos || value.find('"') != std::string::npos) { |
|
containsDelim = true; |
|
output << '"'; |
|
} |
|
|
|
for (auto& symbol : value) { |
|
if (symbol == '"') { |
|
output << '"' << symbol; |
|
} else { |
|
output << symbol; |
|
} |
|
} |
|
|
|
if (containsDelim) { |
|
output << '"'; |
|
} |
|
|
|
return output.str(); |
|
} |
|
|
|
void Marketplace::clear() |
|
{ |
|
std::for_each(sellers_.begin(), sellers_.end(), [](auto& seller) { |
|
if (seller->getUuidAsString() == "11111111-1111-1111-1111-111111111111") { |
|
for (auto& article : seller->getArticles()) { |
|
article->setState(Article::State::DELETE); |
|
} |
|
} else { |
|
seller->setState(Seller::State::DELETE); |
|
} |
|
}); |
|
std::for_each(sales_.begin(), sales_.end(), |
|
[](auto& sale) { sale->setState(Sale::State::DELETE); }); |
|
storeToDb(); |
|
} |