this is the second version of my BankingSystem in C++ for the first one go here: Banking System console app in C++
I did quite a lot of changes since the last version mainly spliting the User class into Account, Customer and Transaction classes as suggested by @SimonLehman so lets get into the code.
Customer
header file
#pragma once
#include <string>
class Customer
{
private:
std::string name;
std::string address;
size_t id;
public:
Customer(size_t id, const std::string& name, const std::string& address);
~Customer();
void PrintCustomerInfo();
const std::string& GetName();
const std::string& GetAddress();
const size_t GetId();
};
cpp file
#include "Customer.h"
#include <iostream>
Customer::Customer(size_t id, const std::string& name, const std::string& address) : id(id), name(name), address(address)
{
}
Customer::~Customer()
{
}
void Customer::PrintCustomerInfo()
{
std::cout << "Costumer info - id : " << id << ", name: " << name << ", address: " << address << '\n';
}
const std::string& Customer::GetAddress()
{
return address;
}
const std::string& Customer::GetName()
{
return name;
}
const size_t Customer::GetId()
{
return id;
}
nothing too complicated just some fields and a function that prints the info of a customer.
Account
header file
#pragma once
#include "Customer.h"
#include <vector>
class Transaction;
using Money = std::int_least16_t;
class Account
{
private:
Customer customer;
Money balance;
size_t accountNumber;
std::vector<Transaction*> transactionList;
public:
Account(size_t accountNumber, const Customer& customer, const Money& balance);
~Account();
void PrintAccountInfo();
const Customer& GetCustomer();
const Money& GetBalance();
size_t GetAccountNumber();
void MoneyMovement(const Money& moneyToMove);
const std::vector<Transaction*>& GetTransactionList();
void ProccessTransaction(const Account& accountTo, const Money& transactionAmount);
};
cpp file
#include "Account.h"
#include "Transaction.h"
Account::Account(size_t accountNumber, const Customer& customer, const Money& balance) : accountNumber(accountNumber), customer(customer), balance(balance)
{
}
Account::~Account()
{
for (Transaction* transaction : transactionList)
{
delete transaction;
}
}
const Customer& Account::GetCustomer()
{
return customer;
}
const Money& Account::GetBalance()
{
return balance;
}
size_t Account::GetAccountNumber()
{
return accountNumber;
}
void Account::MoneyMovement(const Money& moneyToMove)
{
balance += moneyToMove;
}
const std::vector<Transaction*>& Account::GetTransactionList()
{
return transactionList;
}
void Account::ProccessTransaction(const Account& accountTo, const Money& transactionAmount)
{
Transaction *transaction = new Transaction(accountTo, transactionAmount);
transactionList.emplace_back(transaction);
MoneyMovement(transactionAmount);
}
void Account::PrintAccountInfo()
{
customer.PrintCustomerInfo();
std::cout << "Account- account number: " << accountNumber << ", balance: " << balance << '\n';
std::cout << "Transaction History: \n";
for (Transaction *transaction : transactionList)
{
transaction->PrintTransactionInfo();
}
}
the Account class holds a list of all transactions, balance the customer its tied to and accountNumber, it also contains the methods for money manipulations from here like MoneyMovement and ProccessTransaction, the ProccessTransactions creates a new transaction pointer, I add the transaction to the transactionList and then change the balance with MoneyMovement.
Transaction
header file
#pragma once
#include <iostream>
#include <vector>
#include "Account.h"
using Money = std::int_least16_t;
class Transaction
{
Money transactionAmount;
Account accountTo;
public:
Transaction(const Account& accountTo, const Money& transactionAmount);
~Transaction();
void PrintTransactionInfo();
};
cpp file
#include "Transaction.h"
#include "Account.h"
Transaction::Transaction(const Account& accountTo, const Money& transactionAmount) : accountTo(accountTo), transactionAmount(transactionAmount)
{
}
Transaction::~Transaction()
{
}
void Transaction::PrintTransactionInfo()
{
Customer customerTo = accountTo.GetCustomer();
customerTo.PrintCustomerInfo();
std::cout << "Transaction Ammount: " << transactionAmount << '\n';
}
the Transaction class represent a singular transaction, it holds the account which the money came from all went to (might need to work on the name accountTo) and the amount of money moved between accounts, because a certain Account uses the transaction itself I see no need to provide it with itself.
I also added Print methods for testing purposes.
User
header file
#pragma once
#include <string>
#include <vector>
#include "Account.h"
class User
{
private:
size_t id;
std::string username;
std::string password;
Account account;
public:
User(size_t id, const std::string& username, std::string& password, const Account& account);
~User();
size_t GetId();
const std::string& GetUsername();
const std::string& GetPassword();
const Account& GetAccount();
};
cpp file
#include <iostream>
#include "HashPassword.h"
#include "User.h"
User::User(size_t id, const std::string& username, std::string& password, const Account& account) : id(id), username(username), account(account)
{
password = HashPassword(password);
this->password = password;
std::cout << password << '\n';
}
User::~User()
{
}
size_t User::GetId()
{
return id;
}
const std::string& User::GetUsername()
{
return username;
}
const std::string& User::GetPassword()
{
return password;
}
const Account& User::GetAccount()
{
return account;
}
this is the User class which stores the id, the username, the password, and an account that is tied to it.
UserRepository
header file
#pragma once
#include <vector>
#include "User.h"
class UserRepository
{
private:
std::vector<User> mainBrachRepo;
public:
UserRepository();
~UserRepository();
std::vector<User>& GetMainBranchRepository();
void AddUser(const std::string& username, std::string password, const Account& account, std::vector<User>& repository);
void PrintAllUsers(std::vector<User>& repository);
User* FindUserByUsername(std::string& username, std::vector<User>& repository);
};
cpp file
#include <iostream>
#include "UserRepository.h"
UserRepository::UserRepository()
{
}
UserRepository::~UserRepository(){}
std::vector<User>& UserRepository::GetMainBranchRepository()
{
return mainBrachRepo;
}
void UserRepository::AddUser(const std::string& username, std::string password, const Account& account, std::vector<User>& repository)
{
size_t id = repository.size() + 1;
repository.emplace_back(id, username, password, account);
}
void UserRepository::PrintAllUsers(std::vector<User>& repository)
{
for(User& user : repository)
{
std::cout << user.GetUsername() << ", ";
}
std::cout << '\n';
}
User* UserRepository::FindUserByUsername(std::string& username, std::vector<User>& repository)
{
for (User &user : repository)
{
if (user.GetUsername() == username)
{
return &user;
}
}
return nullptr;
}
and finnaly the repository that stores users, its only field is the repository itself, I also added room for more repositories being present, I still did not implemented auto id, and account number assigning for my customers and accounts, only the users for now so the name maybe will be changed to something else later as it will store no only just users, at least this is my idea for now.
if you checked my previous post you might notice that there is no authentication system, I haven't gotten around updating it to fit my new model.
if you want to run the code download it from my github you can find it on version 1 of the post but the github repo itself gets updated.
int_least16_t
has a very small range, so it’s a strange choice to use formoney
. I doubt it will be sufficient. \$\endgroup\$