본문으로 바로가기

은행 계좌 관리 프로그램 ver 1.1

category Java/Java 2020. 9. 3. 19:25
/*
 * @author  : Charlie Lee
 * @date    : 2020-09-03
 * @email   : find1086@gmail.com
 *
 * @info    : simple bank account manage program.
 */

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

public class GenericBankingSystem {
    private static final BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    private static final Map<String, List<BankAccount>> accountsMap = new HashMap<>();
    private static final List<BankUser> userList = new ArrayList<>();

    private static Long accountId = 0L;
    private static final GenericBankingSystem bankSystem = GenericBankingSystem.getInstance();
    private GenericBankingSystem() {}
    public static GenericBankingSystem getInstance() {
        if(bankSystem == null) return new GenericBankingSystem();
        return bankSystem;
    }

    public static void main(String[] args) throws IOException {
        System.out.println("Welcome to Bank System.");
        bankSystem.run();
    }

    public void run() throws IOException {
        boolean flag = true;
        while(flag) {
            bankSystem.addAccount();
            System.out.print("successfully added. do you want to add more? (y/n) : ");
            String addmore = br.readLine().toLowerCase();
            if(!addmore.equals("y")) flag = false;
        }
        bankSystem.manageAccount();
    }

    private void addAccount() throws IOException {
        boolean flag = true;
        String accountNumber = "";
        while(flag) {
            System.out.println("type account number please.");
            accountNumber = validateFormat(br.readLine());
            if(accountNumber != null) flag = checkDuplicatedAccountNumber(accountNumber);
            else System.out.println("it seems not valid account number format.");
        }
        System.out.print("type username for adding this account : ");
        String username = br.readLine();
        BankUser user;
        if(!accountsMap.containsKey(username)) {
            user = new BankUser(username);
        } else {
            user = userList.stream()
                           .filter(name -> (name.getUsername()).equals(username))
                           .findFirst()
                           .orElse(null);
        }
        if(user != null) {
            user.addAccount(new BankAccount(++accountId, accountNumber));
            userList.add(user);
            accountsMap.put(username, user.getAccountList());
        } else {
            throw new Error("Unexpected Error! contact to the Administrator.");
        }
    }

    private String validateFormat(String text) {
        String koreanFormat = "^[0-9]{3,6}+[-]?[0-9]{2,6}+[-]?[0-9]{1,7}+([-]?[0-9]{1,7})?$";
        if(text.matches(koreanFormat)) return text;
        return null;
    }

    private boolean checkDuplicatedAccountNumber(String accountNumber) {
        boolean exist = bankSystem.findDuplicatedAccountNumer(accountNumber);
        if(exist) System.out.println("this number is already exist. try other please.");
        return exist;
    }

    private boolean findDuplicatedAccountNumer(String number) {
        if(userList.size() <= 0) return false;
        return userList.stream().anyMatch(user -> accountsMap.get(user.getUsername())
                                                                      .stream()
                                                                      .anyMatch(v -> (v.getAccountNumber()).equals(number)));
    }

    private void manageAccount() throws IOException {
        boolean flag = true;
        while (flag) {
            String name = chooseUserAccount();
            List<BankAccount> accountsOfanUser = accountsMap.get(name);
            bankSystem.printUserAccount(accountsOfanUser);
            // specify which account state change.
            BankAccount account = bankSystem.chooseOneAccount(accountsOfanUser);
            bankSystem.controlAccount(account);
            flag = bankSystem.continueToManage();
        }
    }

    private boolean continueToManage() throws IOException {
        System.out.println("would you like to return to select user? (y/n)");
        String value = br.readLine().toLowerCase();
        if (value.equals("n")) {
            System.out.println("would you like to go back selecting account menu ? (y/n) : ");
            value = br.readLine().toLowerCase();
            if(value.equals("n")) {
                System.out.println("would you like to go back first step? (y/n) : n will shut down program) : ");
                value = br.readLine().toLowerCase();
                if(value.equals("n")) {
                    System.out.println("okay. program will be shut down.");
                    br.close();
                } else {
                    System.out.println("Welcome back to account registration.");
                    bankSystem.run();
                }
            } else {
                bankSystem.manageAccount();
            }
            return false;
        }
        return true;
    }

    private BankAccount chooseOneAccount(List<BankAccount> accountsOfanUser) throws IOException {
        System.out.println("which account's balance do you want to change?");
        System.out.print("please choose number in [], not account number : ");
        int accountId = parseToInt(br.readLine()) - 1;
        return accountsOfanUser.get(accountId);
    }

    private void printUserAccount(List<BankAccount> accountsOfanUser) {
        System.out.println("The user has those accounts: ");
        for (int i = 1; i <= accountsOfanUser.size(); i++) {
            System.out.println("[" + i + "] " + accountsOfanUser.get(i - 1));
        }
    }

    private String chooseUserAccount() throws IOException {
        String name;
        do {
            System.out.println("::: user account list :::");
            Set<String> key = accountsMap.keySet();
            for (String o : key) {
                System.out.print(o + " ");
            }
            System.out.println("\nwhich users account do you want manage? : ");
            name = br.readLine();
        } while (!bankSystem.validateRegisteredUser(name));
        return name;
    }

    private boolean validateRegisteredUser(String name) {
        if (!accountsMap.containsKey(name)) {
            System.out.println("this user seems not registered yet.");
            return false;
        }
        return true;
    }

    private void controlAccount(BankAccount account) throws IOException {
        boolean changeMoneyProcess = true;
        int chooseNum;
        while (changeMoneyProcess) {
            System.out.println("what would you want to do? choose number please.");
            System.out.println("[1] deposit [2] withdraw [3] show money balance");
            chooseNum = parseToInt(br.readLine());
            switch (chooseNum) {
                case 1: {
                    System.out.println("how much money do you want to deposit ?");
                    account.depositMoney(parseToDouble(br.readLine()));
                    break;
                }
                case 2: {
                    System.out.println("how much money do you want to withdraw ?");
                    account.withdrawMoney(parseToDouble(br.readLine()));
                    break;
                }
                case 3:
                    break;
                default:
                    System.out.println("not service this number yet.");
            }
            System.out.printf("money balance : %5.2f\n", account.getMoney());
            changeMoneyProcess = wantToContinueChangeMoney();
        }
    }

    private boolean wantToContinueChangeMoney() throws IOException {
        System.out.println("would you want to continue changing money balance ? (y/n)");
        return !(br.readLine()).equals("n");
    }

    private static Integer parseToInt(String text) throws IOException {
        boolean isAbleToParseInt = false;
        int parsedInt = 0;
        while (!isAbleToParseInt) {
            try {
                parsedInt = Integer.parseInt(text);
                isAbleToParseInt = true;
            } catch (NumberFormatException nfe) {
                System.out.println("it seems not number! please check again.");
                text = br.readLine();
            }
        }
        return parsedInt;
    }

    private static Double parseToDouble(String text) throws IOException {
        boolean isAbleToParseDouble = false;
        double parsedDouble = 0;
        while (!isAbleToParseDouble) {
            try {
                parsedDouble = Double.parseDouble(text);
                isAbleToParseDouble = true;
            } catch (NumberFormatException nfe) {
                System.out.println("it seems not number! please check again.");
                text = br.readLine();
            }
        }
        return parsedDouble;
    }
}

class BankUser {
    private final String username;
    private final List<BankAccount> accountList = new ArrayList<>();

    public BankUser(String username) {
        this.username = username;
    }

    public String getUsername() {
        return username;
    }

    public void addAccount(BankAccount account) {
        accountList.add(account);
    }

    public List<BankAccount> getAccountList() {
        return accountList;
    }

    @Override
    public String toString() {
        return "BankUser{" +
                "username='" + username + '\'' +
                ", accountList=" + accountList +
                '}';
    }
}

class BankAccount {
    private final long accountId;
    private final String accountNumber;
    private final LocalDateTime regDate;
    private double money;
    public BankAccount(long accountId, String accountNumber) {
        this.accountId = accountId;
        this.accountNumber = accountNumber;
        this.regDate = LocalDateTime.now();
    }

    public String getAccountNumber() {
        return accountNumber;
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (!(o instanceof BankAccount)) return false;
        BankAccount that = (BankAccount) o;
        return accountId == that.accountId &&
                Double.compare(that.money, money) == 0 &&
                Objects.equals(accountNumber, that.accountNumber);
    }

    @Override
    public int hashCode() {
        return Objects.hash(accountId, accountNumber, money);
    }

    @Override
    public String toString() {
        return  "accountNumber: " + accountNumber +
                "\n\tmoney: " + money +
                "\n\tregDate: " + regDate.format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")) + "\n";
    }

    public double getMoney() {
        return money;
    }

    public void depositMoney(double money) {
        this.money += money;
    }

    public void withdrawMoney(double money) {
        double temp = this.money -= money;
        if (temp < 0) {
            throw new Error("you can't withdraw that money.");
        }
        this.money = temp;
    }
}

// http://colorscripter.com/s/rcw1z3L
// http://colorscripter.com/s/rcw1z3L
// http://colorscripter.com/s/rcw1z3L

'Java > Java' 카테고리의 다른 글

java 슈퍼 타입 토큰을 활용한 map 및 list 구현  (1) 2021.07.29
간단한 은행 계좌 관리 프로그램  (0) 2020.08.30
Java enum 활용법  (0) 2020.07.29