summaryrefslogtreecommitdiff
path: root/include/book_store/store.hh
blob: 29c72db4e098879618c5cdd8366baf1c57e32ee4 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#ifndef BOOK_STORE_HH
#define BOOK_STORE_HH

#include <cctype>
#include <cstddef>
#include <functional>
#include <optional>
#include <string_view>
#include <utility>
#include <vector>

#include <book_store/book.hh>
#include <book_store/book_count.hh>
#include <book_store/customer.hh>
#include <book_store/price.hh>
#include <book_store/purchase_error.hh>

namespace book_store {
class store {
private:
  using books_type = std::vector<product::book>;
  using customer_type = consumer::customer;
  using customer_container = std::vector<customer_type>;
  // An `std::unordered_map` would be more appropriate here, but
  // here we are. While we aren't using a proper database, we can
  // take these liberties.
  using transactions_type = std::vector<std::pair<std::size_t, product::book>>;
  using discount_percent_type = double;
  using size_type = std::size_t;

  size_type _books_max_size;
  size_type _customers_max_size;
  books_type _books;
  customer_container _customers;
  transactions_type _transactions;
  product::price::usd _membership_fee;
  discount_percent_type _membership_discount_percent;

public:
  store() = default;
  store(size_type books_max_size, size_type customers_max_size)
      : _books_max_size(books_max_size),
        _customers_max_size(customers_max_size) {}
  store(size_type books_max_size, size_type customers_max_size,
        product::price::usd membership_fee,
        discount_percent_type membership_discount_percent)
      : _books_max_size(books_max_size),
        _customers_max_size(customers_max_size),
        _membership_fee(membership_fee),
        _membership_discount_percent(membership_discount_percent) {}
  store(const store &) = default;
  store(store &&) = default;

  auto append_book(const product::book &book) -> void;
  auto append_customer(const customer_type &person) -> void;
  auto
  purchase_book(size_type person_id, std::string_view isbn,
                product::book_count count) -> std::optional<purchase_error>;
  auto tick_year() -> void;
  auto membership_fee(product::price::usd fee) -> void;
  auto
  membership_discount_percent(discount_percent_type discount_percent) -> void;

  [[nodiscard]] auto books_size() const noexcept -> size_type;
  [[nodiscard]] auto people_size() const noexcept -> size_type;
  [[nodiscard]] auto books_max_size() const noexcept -> size_type;
  [[nodiscard]] auto people_max_size() const noexcept -> size_type;
  [[nodiscard]] auto membership_fee() const noexcept -> product::price::usd;
  [[nodiscard]] auto
  membership_discount_percent() const noexcept -> discount_percent_type;
  auto find_person_by_id(size_type person_id) -> std::optional<customer_type>;
  auto find_book_by_isbn(std::string_view isbn)
      -> std::optional<std::reference_wrapper<product::book>>;
  auto
  find_books_by_title(std::string_view title) -> std::vector<product::book>;
  auto
  find_books_by_author(std::string_view name) -> std::vector<product::book>;
  auto transactions_by_id(size_type person_id) -> std::vector<product::book>;
  auto books() -> books_type &;
  auto people() -> customer_container &;

  auto operator=(const store &) -> store & = default;
  auto operator=(store &&) -> store & = default;
};
} // namespace book_store

#endif // BOOK_STORE_HH