#include #include #include #include #include #include using namespace std; class Date { private: int day; int month; int year; public: Date() {} Date(int day, int month, int year) { this->day = day; this->month = month; this->year = year; } void set_date(const string& date_str) { // Extract day, month, and year from the date string int day = stoi(date_str.substr(0, 2)); int month = stoi(date_str.substr(3, 2)); int year = stoi(date_str.substr(6, 4)); // Set the date this->day = day; this->month = month; this->year = year; cout << "date: " << day << "-" << month << "-" << year << endl; } int get_day() const { return day; } int get_month() const { return month; } int get_year() const { return year; } }; class Bill { public: Bill(double amt) : amount(amt), paid(false) {} virtual string get_type() const = 0; double get_amount() const { return amount; } bool is_paid() const { return paid; } void mark_paid() { paid = true; } private: double amount; bool paid; }; class WaterBill : public Bill { public: WaterBill(double amt) : Bill(amt) {} string get_type() const override { return "Water Bill"; } }; class ElectricityBill : public Bill { public: ElectricityBill(double amt) : Bill(amt) {} string get_type() const override { return "Electricity Bill"; } }; class Account { public: Account() {} Account(int num, double bal) : account_num(num), balance(bal) {} virtual string get_account_type() const { return "hoi"; } virtual ~Account() {} // add virtual destructor int get_account_num() const { return account_num; } double get_balance() const { return balance; } void deposit(double new_balance) { balance += new_balance; } void withdraw(double new_balance) { balance -= new_balance; } private: int account_num; double balance; }; class CheckingAccount : public Account { public: CheckingAccount() : Account() {} CheckingAccount(int num, double bal) : Account(num, bal) {} string get_account_type() const override { return "Checking Account"; } }; class SavingsAccount : public Account { public: SavingsAccount() : Account() {} SavingsAccount(int num, double bal) : Account(num, bal) {} string get_account_type() const override { return "Savings Account"; } }; class CreditCard : public Account { private: Account* linked_account; public: CreditCard(int account_num, double bal, Account* linked_account) : Account(account_num, bal), linked_account(linked_account) {} string get_account_type() const override { return "Creditcard Account"; } Account* get_linked_account() const { return linked_account; } ~CreditCard() { } }; class User { public: User(string username, string password, string role) : username(username), password(password), role(role) {} string get_username() const { return username; } string get_password() const { return password; } string get_role() const { return role; } vector>& get_accounts() { return accounts; } void add_account(shared_ptr account) { accounts.push_back(account); } private: vector> accounts; string username; string password; string role; }; class Bank { private: vector checking_accounts; vector savings_accounts; vector creditcard_accounts; vector users; User* current_user; string current_user_role; unordered_map> user_accounts; vector open_bills; unordered_map> user_bills; public: Bank() { // create some initial accounts checking_accounts.push_back(CheckingAccount(123, 1000.0)); checking_accounts.push_back(CheckingAccount(444, 200.0)); savings_accounts.push_back(SavingsAccount(456, 5000.0)); checking_accounts.push_back(CheckingAccount(789, 2500.0)); savings_accounts.push_back(SavingsAccount(321, 4000.0)); // added savings account for alice // initialize bills for henk and alice accounts user_bills["alice"].push_back(new WaterBill(75.0)); // bill for alice user_bills["alice"].push_back(new ElectricityBill(100.0)); // bill for alice user_bills["henk"].push_back(new WaterBill(50.0)); // bill for henk user_bills["henk"].push_back(new ElectricityBill(80.0)); // bill for henk // create some initial users users.push_back(User("alice", "pass1", "customer")); users.push_back(User("henk", "zomer", "customer")); users.push_back(User("bob", "pass2", "cashier")); users.push_back(User("charlie", "pass3", "director")); // add creditcard accounts for alice and henk CheckingAccount* alice_linked_acc = nullptr; CheckingAccount* henk_linked_acc = nullptr; for (auto& acc : checking_accounts) { if (acc.get_account_num() == 123) { alice_linked_acc = &acc; } else if (acc.get_account_num() == 789) { henk_linked_acc = &acc; } } creditcard_accounts.push_back(CreditCard(8888, -500.0, alice_linked_acc)); creditcard_accounts.push_back(CreditCard(9999, -1000.0, henk_linked_acc)); // populate the user_accounts map with the accounts of each user for (auto& user : users) { if (user.get_username() == "alice") { // add alice's accounts user_accounts[user.get_username()].push_back(&checking_accounts[0]); user_accounts[user.get_username()].push_back(&savings_accounts[0]); user_accounts[user.get_username()].push_back(&creditcard_accounts[0]); } else if (user.get_username() == "henk") { // add henk's accounts user_accounts[user.get_username()].push_back(&checking_accounts[1]); user_accounts[user.get_username()].push_back(&checking_accounts[2]); user_accounts[user.get_username()].push_back(&savings_accounts[1]); user_accounts[user.get_username()].push_back(&creditcard_accounts[1]); } else { for (auto& acc : checking_accounts) { user_accounts[user.get_username()].push_back(&acc); } for (auto& acc : savings_accounts) { user_accounts[user.get_username()].push_back(&acc); } } } } // function to find user by username and password User* find_user(string username, string password) { for (auto& user : users) { if (user.get_username() == username && user.get_password() == password) { return &user; } } return nullptr; } bool login(string username, string password) { User* user = find_user(username, password); if (user != nullptr) { current_user = user; current_user_role = user->get_role(); return true; } else { return false; } } void logout() { current_user = nullptr; current_user_role = ""; } bool is_logged_in() const { return current_user != nullptr; } string get_current_user_role() const { return current_user_role; } bool has_access_to_account(Account* account) const { if (!is_logged_in()) { return false; } // check if the account belongs to the current user for (auto acc : user_accounts.at(current_user->get_username())) { if (acc == account) { return true; } } // check if the user has the required role to access the account if (current_user_role == "cashier") { return true; } else if (current_user_role == "director") { return true; } else { return false; } } // function to deposit money into an account void deposit(int account_num, double amount) { for (auto acc : user_accounts.at(current_user->get_username())) { if (acc->get_account_type() == "Creditcard Account") { acc->deposit(amount-0.5); cout << "deposit of " << amount << " made to credit card account " << account_num << endl; return; } else if (acc->get_account_num() == account_num) { acc->deposit(amount); cout << "deposit of " << amount << " made to credit card account " << account_num << endl; } } } // function to withdraw money from an account bool withdraw(int account_num, double amount) { for (auto acc : user_accounts.at(current_user->get_username())) { if (acc->get_account_type() == "Creditcard Account") { acc->withdraw(amount + 0.5); cout << "withdrawal of " << amount << " from credit card account " << account_num << endl; return true; } else if (acc->get_account_num() == account_num) { acc->withdraw(amount); cout << "withdrawal of " << amount << " from credit card account " << account_num << endl; return true; } } return false; } void view_balance(int account_num) { bool found = false; for (auto& acct : user_accounts[current_user->get_username()]) { if (acct->get_account_num() == account_num) { cout << "Balance: $" << acct->get_balance() << endl; found = true; break; } } if (!found) { cout << "Account not found." << endl; } } void view_bills() { for (auto bill : open_bills) { cout << bill->get_type() << ": $" << bill->get_amount() << endl; } } void add_bill(Bill * bill) { open_bills.push_back(bill); cout << bill->get_type() << " added." << endl; } void pay_bill(Bill* bill, int account_num) { // find the account with the given account number Account* account = nullptr; for (auto& acc : user_accounts[current_user->get_username()]) { if (acc->get_account_num() == account_num) { account = acc; break; } } if (account == nullptr) { cout << "Account not found." << endl; return; } if (account->get_account_type() == "Creditcard Account") { bill->mark_paid(); account->withdraw(-(bill->get_amount()+0.5)); } else { // check if there are sufficient funds in the account if (bill->get_amount() > account->get_balance()) { cout << "Insufficient funds." << endl; return; } // mark the bill as paid and deduct the amount from the account bill->mark_paid(); account->withdraw(bill->get_amount()); } } vector get_user_accounts() const { vector accounts; if (!is_logged_in()) { return accounts; } // retrieve the accounts associated with the current user auto user_account_ptrs = user_accounts.at(current_user->get_username()); for (auto account_ptr : user_account_ptrs) { accounts.push_back(account_ptr); } return accounts; } vector get_user_bills(string username) { return user_bills[username]; } void add_interest(Date current_date) { if (current_date.get_month() == 12 && current_date.get_day() == 31) { for (CheckingAccount& checking_account : checking_accounts) { double interest_rate = 0.01; double interest = checking_account.get_balance() * interest_rate; checking_account.deposit(interest); // double interest if it's 31st December } for (SavingsAccount& savings_account : savings_accounts) { double interest_rate = 0.05; double interest = savings_account.get_balance() * interest_rate; savings_account.deposit(interest); // double interest if it's 31st December } cout << "Interest added to accounts" << endl; } else { cout << "No interest added today." << endl; } } void negative_monthly_interest(Date current_date) { if (current_date.get_day() == 28) { for (CheckingAccount& checking_account : checking_accounts) { if (checking_account.get_balance() < 0) { double interest_rate = 0.03; double interest = checking_account.get_balance() * interest_rate; checking_account.withdraw(interest); // Negative interest added to checking account, due to balance being negative cout << "Negative interest added to checking accounts" << endl; } } } } void deduce_creditcard_balance(const Date& current_date) { if (current_date.get_day() >= 28) { for (CreditCard& creditcard_account : creditcard_accounts) { auto linked_acc = creditcard_account.get_linked_account(); double cc_balance = creditcard_account.get_balance(); if (cc_balance < 0) { linked_acc->withdraw((-1 * cc_balance)); } else { linked_acc->deposit((cc_balance)); } if (cc_balance <= 0) { creditcard_account.deposit(-1 * cc_balance); } else { creditcard_account.withdraw(cc_balance); } cout << "creditcard balance is deducted from checking account." << endl; } } } User* get_user(const string& username) { for (auto& user : users) { if (user.get_username() == username) { return &user; } } return nullptr; } bool add_account(const string& username) { User* user = get_user(username); if (user == nullptr) { cout << "Error: User not found." << endl; return false; } int choice; bool added = false; do { cout << endl << "Select account type to add: " << endl; cout << "1. Checking Account" << endl; cout << "2. Savings Account" << endl; cout << "3. Credit Card Account" << endl; cout << "4. Cancel" << endl; cout << "Choice: "; cin >> choice; cout << endl; switch (choice) { case 1: { int account_num; double balance; cout << "Enter account number: "; cin >> account_num; cout << "Enter balance: "; cin >> balance; auto acc = make_shared(account_num, balance); user->add_account(acc); cout << "Checking account added successfully." << endl; added = true; break; } case 2: { int account_num; double balance; cout << "Enter account number: "; cin >> account_num; cout << "Enter balance: "; cin >> balance; auto acc = make_shared(account_num, balance); user->add_account(acc); cout << "Savings account added successfully." << endl; added = true; break; } case 3: { int account_num; double balance; int linked_account_num; cout << "Enter account number: "; cin >> account_num; cout << "Enter balance: "; cin >> balance; cout << "Enter checking account number to link creditcard account to: "; cin >> linked_account_num; CreditCard* user_linked_acc = nullptr; for (auto& acc : creditcard_accounts) { if (acc.get_account_num() == linked_account_num) { user_linked_acc = &acc; break; } } auto acc = make_shared(account_num, balance, user_linked_acc); if (user_linked_acc == nullptr) { cout << "Error: Invalid linked account number. Credit card account not added." << endl; } else { user->add_account(acc); cout << "Credit card account added successfully." << endl; added = true; } break; } case 4: break; default: cout << "Invalid choice. Please try again." << endl; break; } } while (choice != 4 && !added); return added; } vector get_user_accounts(const string& username) const { vector accounts; auto it = user_accounts.find(username); if (it != user_accounts.end()) { for (auto account : it->second) { accounts.push_back(account); } } return accounts; } void list_accounts(const string& username) { User* user = get_user(username); if (user == nullptr) { cout << "Error: User not found." << endl; return; } vector> accounts; for (auto acc : user_accounts[username]) { if (auto ca = dynamic_cast(acc)) { accounts.push_back(make_shared(*ca)); } else if (auto sa = dynamic_cast(acc)) { accounts.push_back(make_shared(*sa)); } else if (auto cca = dynamic_cast(acc)) { accounts.push_back(make_shared(*cca)); } } cout << "Number of accounts for user " << username << ": " << accounts.size() << endl; for (auto acc : accounts) { cout << "Account number for user " << username << ": " << acc->get_account_num() << endl; } cout << endl << "Accounts for user " << username << ":" << endl; for (auto acc : accounts) { if (auto ca = dynamic_pointer_cast(acc)) { cout << ca->get_account_type() << " (" << ca->get_account_num() << "): " << ca->get_balance() << endl; } else if (auto sa = dynamic_pointer_cast(acc)) { cout << sa->get_account_type() << " (" << sa->get_account_num() << "): " << sa->get_balance() << endl; } else if (auto cca = dynamic_pointer_cast(acc)) { cout << cca->get_account_type() << " (" << cca->get_account_num() << "): " << cca->get_balance() << endl; } } } }; int main() { Bank bank; string username, password; Date date(1, 1, 2022); // creates a date object with values 1, 1, 2022 while (true) { cout << "Welcome to the bank. Please login to continue." << endl; cout << "1. Login" << endl; cout << "2. set date" << endl; cout << "3. Quit" << endl; cout << "Enter choice (1-3: "; int choice; cin >> choice; if (choice == 3) { break; } else if (choice == 1) { cout << "Username: "; cin >> username; cout << "Password: "; cin >> password; if (bank.login(username, password)) { cout << "Login successful!" << endl; bank.add_interest(date); bank.deduce_creditcard_balance(date); bank.negative_monthly_interest(date); } else { cout << "Invalid username or password. Please try again." << endl; continue; } } else if (choice == 2) { cout << "date should be in format dd-mm-yyyy" << endl; cout << "set date: "; string input_date; cin >> input_date; date.set_date(input_date); continue; } else { cout << "Invalid choice. Please try again." << endl; continue; } User* user = bank.get_user(username); if (user->get_role() == "customer") { // The user is a customer while (true) { cout << endl << "What would you like to do?" << endl; cout << "1. View bank accounts" << endl; cout << "2. View bills" << endl; cout << "3. Log out" << endl; cout << "Enter choice (1-3): "; cin >> choice; if (choice == 3) { bank.logout(); break; } else if (choice == 2) { cout << "Your bills:" << endl; for (auto bill : bank.get_user_bills(username)) { cout << bill->get_type() << " - $" << bill->get_amount() << endl; } } else if (choice == 1) { vector accounts = bank.get_user_accounts(); cout << endl << "Your accounts:" << endl; int i = 1; map account_map; for (auto acc : accounts) { cout << i << ". " << acc->get_account_type() << " (" << acc->get_account_num() << "): " << acc->get_balance() << endl; account_map[i] = acc; i++; } cout << i << ". Go back" << endl; cout << "Select an account (1-" << i << "): "; int account_choice; cin >> account_choice; if (account_choice == i) { continue; } Account* account = account_map[account_choice]; cout << "Selected account: " << account->get_account_type() << " (" << account->get_account_num() << ")" << endl; while (true) { cout << endl << "What would you like to do?" << endl; cout << "1. Deposit" << endl; cout << "2. Withdraw" << endl; cout << "3. Pay bill" << endl; cout << "4. Go back to main menu" << endl; cout << "Enter choice (1-5): "; cin >> choice; if (choice == 1) { cout << "Enter amount to deposit: "; double amount; cin >> amount; bank.deposit(account->get_account_num(), amount); cout << "Deposit successful. New balance: " << account->get_balance() << endl; } else if (choice == 2) { cout << "Enter amount to withdraw: "; double amount; cin >> amount; if (bank.withdraw(account->get_account_num(), amount)) { cout << "Withdrawal successful. New balance: " << account->get_balance() << endl; } else { cout << "Insufficient funds. Withdrawal unsuccessful." << endl; } } else if (choice == 3) { cout << "Your bills:" << endl; vector user_bills = bank.get_user_bills(username); for (int i = 0; i < user_bills.size(); i++) { cout << i + 1 << ". " << user_bills[i]->get_type() << " - $" << user_bills[i]->get_amount() << endl; } cout << "Select bill: "; int bill_index; cin >> bill_index; if (bill_index <= 0 || bill_index > user_bills.size()) { cout << "Invalid selection." << endl; return 0; } Bill* bill = user_bills[bill_index - 1]; bank.pay_bill(bill, account->get_account_num()); cout << "Bill paid." << endl; } else if (choice == 4) { break; } else { cout << "Invalid choice. Please try again." << endl; } } } } } else if (user->get_role() == "cashier") { while (true) { cout << endl << "What would you like to do?" << endl; cout << "1. View all accounts of a user" << endl; cout << "2. Open a new account for a user" << endl; cout << "3. Log out" << endl; cout << "Enter choice (1-3): "; int choice; cin >> choice; if (choice == 3) { bank.logout(); break; } else if (choice == 1) { cout << "Enter username: "; string username; cin >> username; vector accounts = bank.get_user_accounts(username); if (accounts.empty()) { cout << "No accounts found for user " << username << endl; } else { cout << endl << "Accounts for user " << username << ":" << endl; for (auto acc : accounts) { cout << acc->get_account_type() << " (" << acc->get_account_num() << "): " << acc->get_balance() << endl; } } } else if (choice == 2) { cout << "Enter username: "; string username; cin >> username; if (bank.add_account(username)) { cout << "Account successfully opened for user " << username << endl; bank.list_accounts(username); } else { cout << "Failed to open account for user " << username << endl; } } } } else if (user->get_role() == "director") { // The user is a director } } return 0; }