From b8e7cda86ef93d53cfa93ee18e2fb4e6a929ac59 Mon Sep 17 00:00:00 2001 From: ZhuangYumin Date: Thu, 14 Dec 2023 16:11:58 +0000 Subject: [PATCH] add log and report emplyee --- backend/include/bs-utility.h | 4 +-- backend/include/database.h | 12 ++++++-- backend/src/database.cpp | 54 ++++++++++++++++++++++++++++++++++-- backend/src/engine.cpp | 24 ++++++++++++++-- 4 files changed, 84 insertions(+), 10 deletions(-) diff --git a/backend/include/bs-utility.h b/backend/include/bs-utility.h index 6acecca..9a92a4f 100644 --- a/backend/include/bs-utility.h +++ b/backend/include/bs-utility.h @@ -138,8 +138,8 @@ class FinanceItemClass { class OperationLogItemClass { public: char user_id[31]; - char command[256]; - int fid; + char command[400]; + bool is_worker; }; enum OperationType { diff --git a/backend/include/database.h b/backend/include/database.h index 696caf5..06c0d07 100644 --- a/backend/include/database.h +++ b/backend/include/database.h @@ -43,17 +43,23 @@ class LogDataBase { DriveArray finance_data; DriveArray operation_log_data; int finance_operation_count; + int total_operation_count; public: - ~LogDataBase() { finance_data.write_info(finance_operation_count, 1); } + ~LogDataBase() { + finance_data.write_info(finance_operation_count, 1); + operation_log_data.write_info(total_operation_count, 1); + } void Open(std::string file_name); 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 GenaerateFinanceReport(std::string file_name, - std::vector &ret, + void GenaerateFinanceReport(std::vector &ret, BookDataBase &book_data); int TotalFinanceOperationCount() noexcept { return finance_operation_count; } + void AddOperationRecord(const std::string &user_id, const std::string &cmd, + UserDataBase &user_data); + void FetchOperationRecord(std::vector &ret, bool worker_only); }; #endif // PROTECTOR_DATABASE_HPP \ No newline at end of file diff --git a/backend/src/database.cpp b/backend/src/database.cpp index 528d286..864e2cc 100644 --- a/backend/src/database.cpp +++ b/backend/src/database.cpp @@ -23,6 +23,7 @@ void LogDataBase::Open(std::string file_name) { finance_data.OpenFile(file_name + ".finance"); finance_data.get_info(finance_operation_count, 1); operation_log_data.OpenFile(file_name + ".log"); + operation_log_data.get_info(total_operation_count, 1); } bool UserDataBase::PAM(const std::string &user_id, @@ -276,8 +277,7 @@ std::pair LogDataBase::QueryFinance(int count) { return std::make_pair(total_sell, total_import); } -void LogDataBase::GenaerateFinanceReport(std::string file_name, - std::vector &ret, +void LogDataBase::GenaerateFinanceReport(std::vector &ret, BookDataBase &book_data) { ret.clear(); std::unordered_map> @@ -346,4 +346,54 @@ std::string BookDataBase::GetISBN(int bid) { BookItemClass tmp; full_book_data.read(tmp, bid); return std::string(tmp.ISBN); +} + +void LogDataBase::AddOperationRecord(const std::string &user_id, + const std::string &cmd, + UserDataBase &user_data) { + OperationLogItemClass tmp; + strcpy(tmp.user_id, user_id.c_str()); + std::stringstream ss(cmd); + std::string token; + while (ss >> token) ss << token << ' '; + strcpy(tmp.command, ss.str().c_str()); + tmp.is_worker = false; + if (user_data.GetPrevilege(user_id) == 3) tmp.is_worker = true; + operation_log_data.write(tmp); + total_operation_count++; +} + +void LogDataBase::FetchOperationRecord(std::vector &ret, + bool worker_only) { + ret.clear(); + if (!worker_only) { + for (int i = 1; i <= total_operation_count; i++) { + OperationLogItemClass tmp; + operation_log_data.read(tmp, i); + std::stringstream ss; + ss << std::setw(6) << std::setfill('0') << i << " " << tmp.user_id << " " + << tmp.command; + ret.push_back(ss.str()); + } + } else { + // classify by worker + std::unordered_map> bucket; + std::unordered_map bucket_counter; + for (int i = 1; i <= total_operation_count; i++) { + OperationLogItemClass tmp; + operation_log_data.read(tmp, i); + if (tmp.is_worker) { + std::stringstream ss; + ss << std::setw(6) << std::setfill('0') << ++bucket_counter[tmp.user_id] + << " " << tmp.user_id << " " << tmp.command; + bucket[tmp.user_id].push_back(ss.str()); + } + } + for (auto &i : bucket) { + ret.push_back("---------- " + i.first + " ----------"); + for (auto &j : i.second) { + ret.push_back(j); + } + } + } } \ No newline at end of file diff --git a/backend/src/engine.cpp b/backend/src/engine.cpp index 59f01a2..c651cd9 100644 --- a/backend/src/engine.cpp +++ b/backend/src/engine.cpp @@ -47,6 +47,11 @@ std::vector BookStoreEngineClass::Execute( std::string head = ""; ss >> head; if (head == "quit" || head == "exit") { + if (!login_stack.empty()) + log_data_base.AddOperationRecord(login_stack.top().first, cmd, + user_data_base); + else + log_data_base.AddOperationRecord("[nobody]", cmd, user_data_base); static std::basic_regex quit_regex(R"(^ *(quit|exit) *$)", std::regex_constants::optimize); if (!std::regex_match(cmd, quit_regex)) @@ -63,6 +68,11 @@ std::vector BookStoreEngineClass::Execute( if (cmd[i] != ' ') return std::vector({"Invalid"}); return std::vector(); } + if (!login_stack.empty()) + log_data_base.AddOperationRecord(login_stack.top().first, cmd, + user_data_base); + else + log_data_base.AddOperationRecord("[nobody]", cmd, user_data_base); switch (operation_map[head]) { case OperationType::__Ksu: { return ExecuteSu(cmd, login_stack); @@ -409,7 +419,12 @@ std::vector BookStoreEngineClass::ExecuteLog( std::regex_constants::optimize); if (!std::regex_match(cmd, log_regex)) return std::vector({"Invalid"}); - return std::vector(); + if (login_stack.empty() || + user_data_base.GetPrevilege(login_stack.top().first) < 7) + return std::vector({"Invalid"}); + std::vector ret; + log_data_base.FetchOperationRecord(ret, false); + return ret; } std::vector BookStoreEngineClass::ExecuteReport( @@ -428,8 +443,11 @@ std::vector BookStoreEngineClass::ExecuteReport( ss >> token; if (token == "finance") { std::vector ret; - log_data_base.GenaerateFinanceReport(config_dir + "finance_report", ret, - book_data_base); + log_data_base.GenaerateFinanceReport(ret, book_data_base); + return ret; + } else { + std::vector ret; + log_data_base.FetchOperationRecord(ret, true); return ret; } return std::vector();