kima2/src/core/marketplace.cpp

285 lines
8.4 KiB
C++

#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;
}
int Marketplace::getNumArticlesSold()
{
int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, [](int a, const auto& seller) {
return a + seller->numArticlesSold();
});
return sum;
}
int Marketplace::getNumArticlesOffered()
{
int sum = std::accumulate(sellers_.begin(), sellers_.end(), 0, [](int a, const auto& seller) {
return a + seller->numArticlesOffered();
});
return sum;
}
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();
}