From b1592fbf56ffa6211beeb9c8fd7a8c16c953c31a Mon Sep 17 00:00:00 2001 From: ZhuangYumin Date: Thu, 14 Dec 2023 15:47:24 +0000 Subject: [PATCH] upd: add support for report finance --- backend/include/database.h | 6 ++-- backend/src/database.cpp | 70 ++++++++++++++++++++++++++++++++++++++ backend/src/engine.cpp | 14 ++++++++ 3 files changed, 88 insertions(+), 2 deletions(-) diff --git a/backend/include/database.h b/backend/include/database.h index 83428d9..696caf5 100644 --- a/backend/include/database.h +++ b/backend/include/database.h @@ -22,10 +22,10 @@ class UserDataBase { void ChangePassword(const std::string &user_id, const std::string &password); }; class BookDataBase { - DriveArray full_book_data; String2Index ISBN2index, name2index, author2index, keyword2index; public: + DriveArray full_book_data; void Open(std::string file_name); bool HaveISBN(const std::string &ISBN); bool HaveISBN(const std::string &ISBN, BookItemClass &ret); @@ -50,7 +50,9 @@ class LogDataBase { void AddSell(int book_id, int quantity, double total_price); void AddImport(int book_id, int quantity, double total_price); std::pair QueryFinance(int count = -1); - void QueryFinance(int count, std::vector &ret); + void GenaerateFinanceReport(std::string file_name, + std::vector &ret, + BookDataBase &book_data); int TotalFinanceOperationCount() noexcept { return finance_operation_count; } }; diff --git a/backend/src/database.cpp b/backend/src/database.cpp index ce2d7b6..528d286 100644 --- a/backend/src/database.cpp +++ b/backend/src/database.cpp @@ -1,5 +1,9 @@ #include "database.h" +#include +#include +#include + #include "bs-utility.h" #include "lexer.h" void UserDataBase::Open(std::string file_name) { @@ -272,6 +276,72 @@ std::pair LogDataBase::QueryFinance(int count) { return std::make_pair(total_sell, total_import); } +void LogDataBase::GenaerateFinanceReport(std::string file_name, + std::vector &ret, + BookDataBase &book_data) { + ret.clear(); + std::unordered_map> + bucket; // classify by book_id + for (int i = 1; i <= finance_operation_count; i++) { + FinanceItemClass tmp; + finance_data.read(tmp, i); + if (tmp.total_price > 0) { + bucket[tmp.book_id].first += tmp.total_price; + } else { + bucket[tmp.book_id].second -= tmp.total_price; + } + } + std::vector>> tmp; + for (auto &i : bucket) { + tmp.push_back(i); + } + // first, generate a table sorted by sales + sort(tmp.begin(), tmp.end(), + [](const std::pair> &a, + const std::pair> &b) { + return a.second.first > b.second.first; + }); + ret.push_back("Sale Ranking:"); + /** + * The format of each line is: + * [ISBN]\t[Name]\t+[Sales]\t-[Cost] + * + * note that Sales and Profit should have a precision of 2 + */ + for (auto &i : tmp) { + BookItemClass tmp_book; + book_data.full_book_data.read(tmp_book, i.first); + std::stringstream ss; + ss << "+" << std::fixed << std::setprecision(2) << i.second.first << "\t-" + << std::fixed << std::setprecision(2) << i.second.second; + ret.push_back(std::string(tmp_book.ISBN) + "\t" + + std::string(tmp_book.name) + "\t" + ss.str()); + } + // then, generate a table sorted by cost + sort(tmp.begin(), tmp.end(), + [](const std::pair> &a, + const std::pair> &b) { + return a.second.second > b.second.second; + }); + ret.push_back("--------------------"); + ret.push_back("Cost Ranking:"); + /** + * The format of each line is: + * [ISBN]\t[Name]\t-[Cost]\t+[Sales] + * + * note that Cost and Profit should have a precision of 2 + */ + for (auto &i : tmp) { + BookItemClass tmp_book; + book_data.full_book_data.read(tmp_book, i.first); + std::stringstream ss; + ss << "-" << std::fixed << std::setprecision(2) << i.second.second << "\t+" + << std::fixed << std::setprecision(2) << i.second.first; + ret.push_back(std::string(tmp_book.ISBN) + "\t" + + std::string(tmp_book.name) + "\t" + ss.str()); + } +} + std::string BookDataBase::GetISBN(int bid) { BookItemClass tmp; full_book_data.read(tmp, bid); diff --git a/backend/src/engine.cpp b/backend/src/engine.cpp index e4152d3..59f01a2 100644 --- a/backend/src/engine.cpp +++ b/backend/src/engine.cpp @@ -1,6 +1,7 @@ #include "engine.h" #include +#include #include #include #include @@ -418,5 +419,18 @@ std::vector BookStoreEngineClass::ExecuteReport( R"(^ *report( +finance| +employee) *$)", std::regex_constants::optimize); if (!std::regex_match(cmd, report_regex)) return std::vector({"Invalid"}); + if (login_stack.empty() || + user_data_base.GetPrevilege(login_stack.top().first) < 7) + return std::vector({"Invalid"}); + std::stringstream ss(cmd); + std::string token; + ss >> token; + ss >> token; + if (token == "finance") { + std::vector ret; + log_data_base.GenaerateFinanceReport(config_dir + "finance_report", ret, + book_data_base); + return ret; + } return std::vector(); } \ No newline at end of file