diff --git a/.github/workflows/java.yml b/.github/workflows/java.yml new file mode 100644 index 0000000..c5298c3 --- /dev/null +++ b/.github/workflows/java.yml @@ -0,0 +1,16 @@ +name: Java CI +on: [push] + +jobs: + build: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v2 + - name: Set up JDK 21 + uses: actions/setup-java@v2 + with: + java-version: '21' + distribution: 'temurin' + - name: Build with Maven + run: mvn --batch-mode --update-snapshots package \ No newline at end of file diff --git a/.gitignore b/.gitignore index ea1f7b6..277d995 100644 --- a/.gitignore +++ b/.gitignore @@ -3,6 +3,9 @@ out/ !**/src/main/**/out/ !**/src/test/**/out/ .idea +Application/target +DataAccess/target +Presentation/target ### Eclipse ### .apt_generated diff --git a/Application/pom.xml b/Application/pom.xml new file mode 100644 index 0000000..c8522ac --- /dev/null +++ b/Application/pom.xml @@ -0,0 +1,119 @@ + + + 4.0.0 + + is.technologies + Application + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + + + + + + + org.projectlombok + lombok + 1.18.30 + provided + + + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + + ${project.build.directory}/libs + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + true + libs/ + + is.technologies.Main + + + + + + + + + org.apache.maven.plugins + maven-site-plugin + 3.12.1 + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 3.4.2 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.21.0 + + + org.junit.jupiter + junit-jupiter-engine + 5.9.2 + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.0 + + 17 + ${java.home}/bin/javadoc + + + + maven-javadocs + + jar + + + + + + + + \ No newline at end of file diff --git a/Application/src/main/java/Application/Abstractions/Repositories/IBankAccountRepository.java b/Application/src/main/java/Application/Abstractions/Repositories/IBankAccountRepository.java new file mode 100644 index 0000000..fe7c508 --- /dev/null +++ b/Application/src/main/java/Application/Abstractions/Repositories/IBankAccountRepository.java @@ -0,0 +1,44 @@ +package Application.Abstractions.Repositories; + +import Application.Contracts.ResultTypes.BankAccountResult; +import Application.Models.Entites.BankAccount; + +/** + * Репозиторий для управления банковскими счетами. + * Реализует паттерн CRUD для добавления, поиска, обновления и удаления банковских счетов. + */ +public interface IBankAccountRepository { + + /** + * Добавляет новый банковский счет в хранилище данных. + * + * @param account объект банковского счета, который необходимо добавить. + * @return результат операции добавления банковского счета, может содержать сообщение об ошибке или подтверждение успеха. + */ + BankAccountResult AddBankAccount(BankAccount account); + + /** + * Ищет банковский счет в хранилище данных по его идентификатору. + * + * @param id идентификатор банковского счета, который нужно найти. + * @return объект банковского счета, если он существует; {@code null}, если счет не найден. + */ + BankAccount FindBankAccountById(Integer id); + + /** + * Обновляет баланс существующего банковского счета. + * + * @param id идентификатор банковского счета, баланс которого необходимо обновить. + * @param balance новый баланс банковского счета. + * @return результат операции обновления баланса, может содержать сообщение об ошибке или подтверждение успеха. + */ + BankAccountResult UpdateBankAccountBalance(Integer id, Double balance); + + /** + * Удаляет банковский счет из хранилища данных по его идентификатору. + * + * @param id идентификатор банковского счета, который нужно удалить. + * @return результат операции удаления банковского счета, может содержать сообщение об ошибке или подтверждение успеха. + */ + BankAccountResult DeleteBankAccount(Integer id); +} diff --git a/Application/src/main/java/Application/Abstractions/Repositories/IOperationRepository.java b/Application/src/main/java/Application/Abstractions/Repositories/IOperationRepository.java new file mode 100644 index 0000000..2829ae3 --- /dev/null +++ b/Application/src/main/java/Application/Abstractions/Repositories/IOperationRepository.java @@ -0,0 +1,29 @@ +package Application.Abstractions.Repositories; + +import Application.Contracts.ResultTypes.OperationResult; +import Application.Models.Entites.Operation; + +import java.util.ArrayList; + +/** + * Репозиторий для управления операциями с банковскими счетами. + * Реализует паттерн CRUD для добавления операций и получения истории операций. + */ +public interface IOperationRepository { + + /** + * Добавляет новую операцию в хранилище данных. + * + * @param operation операция, которую необходимо добавить в хранилище. + * @return результат операции добавления, может содержать сообщение об ошибке или подтверждение успеха. + */ + OperationResult AddOperation(Operation operation); + + /** + * Извлекает историю операций для конкретного банковского счета. + * + * @param bankAccountId идентификатор банковского счета, для которого нужно получить историю операций. + * @return список операций, выполненных с указанным банковским счетом. + */ + ArrayList GetOperationHistory(Integer bankAccountId); +} diff --git a/Application/src/main/java/Application/Abstractions/Repositories/IUserRepository.java b/Application/src/main/java/Application/Abstractions/Repositories/IUserRepository.java new file mode 100644 index 0000000..14a89cc --- /dev/null +++ b/Application/src/main/java/Application/Abstractions/Repositories/IUserRepository.java @@ -0,0 +1,44 @@ +package Application.Abstractions.Repositories; + +import Application.Contracts.ResultTypes.UserResult; +import Application.Models.Entites.User; + +/** + * Репозиторий для управления операциями с пользователями. + * Использует паттерн CRUD (Create, Read, Update, Delete) для добавления, поиска, обновления и удаления пользователей. + */ +public interface IUserRepository { + + /** + * Добавляет нового пользователя в хранилище данных. + * + * @param user объект пользователя, который необходимо добавить. + * @return результат операции добавления пользователя, может содержать сообщение об ошибке или подтверждение успеха. + */ + UserResult AddUser(User user); + + /** + * Ищет пользователя в хранилище данных по его идентификатору. + * + * @param id идентификатор пользователя, которого нужно найти. + * @return найденный объект пользователя, если он существует; {@code null}, если пользователь не найден. + */ + User FindUserById(Integer id); + + /** + * Обновляет информацию о существующем пользователе в хранилище данных. + * + * @param id идентификатор пользователя, чьи данные нужно обновить. + * @param userUpdate объект с обновленными данными пользователя. + * @return результат операции обновления пользователя, может содержать сообщение об ошибке или подтверждение успеха. + */ + UserResult UpdateUser(Integer id, User userUpdate); + + /** + * Удаляет пользователя из хранилища данных по его идентификатору. + * + * @param id идентификатор пользователя, которого нужно удалить. + * @return результат операции удаления пользователя, может содержать сообщение об ошибке или подтверждение успеха. + */ + UserResult DeleteUser(Integer id); +} diff --git a/Application/src/main/java/Application/Contracts/Interfaces/IUserService.java b/Application/src/main/java/Application/Contracts/Interfaces/IUserService.java new file mode 100644 index 0000000..dac25eb --- /dev/null +++ b/Application/src/main/java/Application/Contracts/Interfaces/IUserService.java @@ -0,0 +1,117 @@ +package Application.Contracts.Interfaces; + +import Application.Contracts.ResultTypes.BankAccountResult; +import Application.Contracts.ResultTypes.OperationResult; +import Application.Contracts.ResultTypes.UserResult; +import Application.Models.Entites.BankAccount; +import Application.Models.Entites.User; + +/** + * Интерфейс, предоставляющий операции для управления пользователями и их банковскими счетами. + * Включает методы для создания, удаления пользователей, управления их друзьями и банковскими счетами, + * а также выполнения различных операций с банковскими счетами. + */ +public interface IUserService { + + /** + * Создание нового пользователя. + * + * @param user объект пользователя, который должен быть создан. + * @return результат операции создания пользователя. + */ + UserResult CreateUser(User user); + + /** + * Удаление пользователя. + * + * @param user объект пользователя, который должен быть удален. + * @return результат операции удаления пользователя. + */ + UserResult DeleteUser(User user); + + /** + * Получение информации о пользователе. + * + * @param user объект пользователя, информацию о котором необходимо получить. + */ + void GetUserInfo(User user); + + /** + * Добавление пользователя в друзья. + * + * @param user объект текущего пользователя. + * @param other объект пользователя, которого нужно добавить в друзья. + */ + void AddFriend(User user, User other); + + /** + * Удаление пользователя из списка друзей. + * + * @param user объект текущего пользователя. + * @param other объект пользователя, которого нужно удалить из друзей. + */ + void RemoveFriend(User user, User other); + + /** + * Добавление нового банковского счета пользователю. + * + * @param user объект пользователя, которому нужно добавить банковский счет. + * @param bankAccount объект банковского счета, который нужно добавить. + * @return результат операции добавления банковского счета. + */ + BankAccountResult addBankAccount(User user, BankAccount bankAccount); + + /** + * Удаление банковского счета пользователя. + * + * @param user объект пользователя, чей банковский счет должен быть удален. + * @param bankAccount объект банковского счета, который нужно удалить. + * @return результат операции удаления банковского счета. + */ + BankAccountResult RemoveBankAccount(User user, BankAccount bankAccount); + + /** + * Проверка баланса банковского счета пользователя. + * + * @param user объект пользователя, чей баланс нужно проверить. + * @param bankAccount объект банковского счета, баланс которого нужно проверить. + * @return результат операции проверки баланса. + */ + OperationResult CheckBalance(User user, BankAccount bankAccount); + + /** + * Пополнение банковского счета. + * + * @param bankAccount объект банковского счета, на который нужно пополнить средства. + * @param amount сумма, которую нужно внести на счет. + * @return результат операции пополнения. + */ + OperationResult Deposit(BankAccount bankAccount, Double amount); + + /** + * Снятие средств с банковского счета. + * + * @param bankAccount объект банковского счета, с которого нужно снять средства. + * @param amount сумма, которую нужно снять со счета. + * @return результат операции снятия средств. + */ + OperationResult Withdraw(BankAccount bankAccount, Double amount); + + /** + * Перевод средств между двумя банковскими счетами. + * + * @param bankAccount1 объект исходного банковского счета. + * @param bankAccount2 объект целевого банковского счета. + * @param amount сумма, которую нужно перевести. + * @return результат операции перевода. + */ + OperationResult Transfer(BankAccount bankAccount1, BankAccount bankAccount2, Double amount); + + /** + * Получение истории операций для конкретного банковского счета. + * + * @param bankAccount объект банковского счета, для которого нужно получить историю операций. + * @return результат операции получения истории. + */ + OperationResult GetOperationHistory(BankAccount bankAccount); +} diff --git a/Application/src/main/java/Application/Contracts/ResultTypes/BankAccountResult.java b/Application/src/main/java/Application/Contracts/ResultTypes/BankAccountResult.java new file mode 100644 index 0000000..16f9318 --- /dev/null +++ b/Application/src/main/java/Application/Contracts/ResultTypes/BankAccountResult.java @@ -0,0 +1,35 @@ +package Application.Contracts.ResultTypes; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Абстрактный класс, представляющий result-type операций с банковским счетом. + * Включает различные типы результатов, такие как успешное выполнение операции или ошибка при создании, обновлении или удалении банковского счета. + */ +public abstract sealed class BankAccountResult + permits BankAccountResult.Success, BankAccountResult.BankAccountCreationError, + BankAccountResult.BankAccountUpdateError, BankAccountResult.BankAccountDeletionError { + + + public static final class Success extends BankAccountResult { + } + + @Getter + @AllArgsConstructor + public static final class BankAccountCreationError extends BankAccountResult { + private final String message; + } + + @Getter + @AllArgsConstructor + public static final class BankAccountUpdateError extends BankAccountResult { + private final String message; + } + + @Getter + @AllArgsConstructor + public static final class BankAccountDeletionError extends BankAccountResult { + private final String message; + } +} diff --git a/Application/src/main/java/Application/Contracts/ResultTypes/OperationResult.java b/Application/src/main/java/Application/Contracts/ResultTypes/OperationResult.java new file mode 100644 index 0000000..0adb251 --- /dev/null +++ b/Application/src/main/java/Application/Contracts/ResultTypes/OperationResult.java @@ -0,0 +1,22 @@ +package Application.Contracts.ResultTypes; + +import lombok.AllArgsConstructor; +import lombok.Getter; +import lombok.NoArgsConstructor; + +/** + * Абстрактный класс, представляющий result-type операции с деньгами. + * Включает два типа результатов: успешное выполнение операции и ошибка при выполнении. + */ +public abstract sealed class OperationResult permits OperationResult.Success, OperationResult.OperationError { + + @NoArgsConstructor + public static final class Success extends OperationResult { + } + + @Getter + @AllArgsConstructor + public static final class OperationError extends OperationResult { + private final String message; + } +} diff --git a/Application/src/main/java/Application/Contracts/ResultTypes/UserResult.java b/Application/src/main/java/Application/Contracts/ResultTypes/UserResult.java new file mode 100644 index 0000000..87b9595 --- /dev/null +++ b/Application/src/main/java/Application/Contracts/ResultTypes/UserResult.java @@ -0,0 +1,33 @@ +package Application.Contracts.ResultTypes; + +import lombok.AllArgsConstructor; +import lombok.Getter; + +/** + * Абстрактный класс, представляющий result-type операций с пользователями. + * Включает различные типы результатов, такие как успешное выполнение операции или ошибка при создании, обновлении или удалении пользователя. + */ +public abstract sealed class UserResult + permits UserResult.Success, UserResult.UserCreationError, UserResult.UserUpdateError, UserResult.UserDeletionError { + + public static final class Success extends UserResult { + } + + @Getter + @AllArgsConstructor + public static final class UserCreationError extends UserResult { + private final String message; + } + + @Getter + @AllArgsConstructor + public static final class UserUpdateError extends UserResult { + private final String message; + } + + @Getter + @AllArgsConstructor + public static final class UserDeletionError extends UserResult { + private final String message; + } +} diff --git a/Application/src/main/java/Application/Managers/UserManager.java b/Application/src/main/java/Application/Managers/UserManager.java new file mode 100644 index 0000000..b20b400 --- /dev/null +++ b/Application/src/main/java/Application/Managers/UserManager.java @@ -0,0 +1,127 @@ +package Application.Managers; + +import Application.Contracts.ResultTypes.OperationResult; +import Application.Models.Entites.BankAccount; +import Application.Models.Entites.Operation; +import Application.Models.Entites.User; + +import java.util.ArrayList; + +/** + * Класс-менеджер для управления данными пользователей, их банковскими счетами и друзьями. + * Предоставляет методы для получения информации о пользователе, добавления/удаления друзей, + * управления банковскими счетами и вывода истории операций. + */ +public record UserManager() { + + /** + * Выводит информацию о пользователе, включая его данные и банковские счета. + * + * @param user объект пользователя, информацию о котором нужно вывести. + */ + public void GetUserInfo(User user) { + if (user == null) { + System.out.println("User data is not available."); + return; + } + + System.out.println("User Information:"); + System.out.println("──────────────────────────────────"); + System.out.printf("ID: %d%n", user.getId()); + System.out.printf("Login: %s%n", user.getLogin()); + System.out.printf("Name: %s%n", user.getName()); + System.out.printf("Age: %d%n", user.getAge()); + System.out.printf("Sex: %s%n", user.getSex()); + System.out.printf("Hair Color: %s%n", user.getHairType()); + + System.out.println("\nBank Accounts:"); + if (user.getBankAccounts().isEmpty()) { + System.out.println("No bank accounts available."); + } else { + user.getBankAccounts().forEach(account -> System.out.printf("Account ID: %d%n", account)); + } + + System.out.println("\nFriends:"); + if (user.getFriends().isEmpty()) { + System.out.println("No friends available."); + } else { + user.getFriends().forEach(friend -> + System.out.printf("Friend ID: %d | Name: %s%n", friend.getId(), friend.getName())); + } + + System.out.println("──────────────────────────────────\n"); + } + + /** + * Добавляет друга пользователю и другому пользователю. + * + * @param user текущий пользователь, добавляющий друга. + * @param other пользователь, который будет добавлен в друзья. + */ + public void AddFriend(User user, User other) { + user.getFriends().add(other); + other.getFriends().add(user); + } + + /** + * Удаляет друга у пользователя и другого пользователя. + * + * @param user текущий пользователь, у которого будет удален друг. + * @param other пользователь, который будет удален из друзей. + */ + public void RemoveFriend(User user, User other) { + user.getFriends().remove(other); + other.getFriends().remove(user); + } + + /** + * Добавляет банковский счет пользователю. + * + * @param user пользователь, которому добавляется банковский счет. + * @param bankAccount банковский счет для добавления. + */ + public void AddBankAccount(User user, BankAccount bankAccount) { + user.getBankAccounts().add(bankAccount.getId()); + } + + /** + * Удаляет банковский счет у пользователя. + * + * @param user пользователь, у которого будет удален банковский счет. + * @param bankAccount банковский счет для удаления. + */ + public void RemoveBankAccount(User user, BankAccount bankAccount) { + user.getBankAccounts().remove(bankAccount.getId()); + } + + /** + * Проверяет баланс банковского счета пользователя. + * + * @param user пользователь, чей баланс проверяется. + * @param bankAccount банковский счет для проверки баланса. + */ + public void CheckBalance(User user, BankAccount bankAccount) { + System.out.println("User: " + user.getId()); + System.out.println("BankAccount: " + bankAccount.getId()); + System.out.println("Balance: " + bankAccount.getBalance()); + } + + /** + * Выводит историю операций по банковскому счету. + * + * @param account банковский счет, для которого нужно вывести историю. + * @param operations список операций, связанных с этим счетом. + * @return результат операции (успех или ошибка). + */ + public OperationResult PrintHistory(BankAccount account, ArrayList operations) { + if (operations == null) { + return new OperationResult.OperationError("Operations can not be null."); + } else { + System.out.println("Account Id: " + account.getId()); + for (Operation operation : operations) { + System.out.println("Operation: " + operation.getType() + "Amount: " + operation.getAmount()); + } + return new OperationResult.Success(); + } + } +} diff --git a/Application/src/main/java/Application/Models/Entites/BankAccount.java b/Application/src/main/java/Application/Models/Entites/BankAccount.java new file mode 100644 index 0000000..029f47e --- /dev/null +++ b/Application/src/main/java/Application/Models/Entites/BankAccount.java @@ -0,0 +1,35 @@ +package Application.Models.Entites; + +import lombok.Getter; +import lombok.Setter; +import Application.Models.Utils.IdGenerator; + +/** + * Класс, представляющий банковский счет пользователя. + * Хранит информацию о счете, балансе и привязанном пользователе. + */ +@Getter +public class BankAccount { + final private Integer id; + + @Setter + private Double balance; + + private final String userLogin; + + private final Integer UserId; + + /** + * Конструктор для создания нового банковского счета. + * Генерирует уникальный идентификатор счета и связывает его с пользователем. + * + * @param idGenerator генератор ID для создания уникального идентификатора счета. + * @param user пользователь, к которому будет привязан новый счет. + */ + public BankAccount(IdGenerator idGenerator, User user) { + this.id = idGenerator.generateBankAccountId(); + this.balance = 0.0; + this.userLogin = user.getLogin(); + this.UserId = user.getId(); + } +} diff --git a/Application/src/main/java/Application/Models/Entites/Operation.java b/Application/src/main/java/Application/Models/Entites/Operation.java new file mode 100644 index 0000000..2b2ee00 --- /dev/null +++ b/Application/src/main/java/Application/Models/Entites/Operation.java @@ -0,0 +1,30 @@ +package Application.Models.Entites; + +import lombok.Getter; +import Application.Models.Enums.OperationType; + +/** + * Класс, представляющий операцию с банковским счетом. + * Хранит информацию о типе операции, сумме и счете, на котором она была проведена. + */ +@Getter +public class Operation { + private final Integer BankAccountId; + + private final OperationType Type; + + private final Double Amount; + + /** + * Конструктор для создания новой операции. + * + * @param bankAccountId идентификатор банковского счета, на котором выполнена операция. + * @param type тип операции (например, депозит или снятие). + * @param amount сумма, участвующая в операции. + */ + public Operation(Integer bankAccountId, OperationType type, Double amount) { + this.BankAccountId = bankAccountId; + this.Type = type; + this.Amount = amount; + } +} diff --git a/Application/src/main/java/Application/Models/Entites/User.java b/Application/src/main/java/Application/Models/Entites/User.java new file mode 100644 index 0000000..dc44a2d --- /dev/null +++ b/Application/src/main/java/Application/Models/Entites/User.java @@ -0,0 +1,61 @@ +package Application.Models.Entites; + +import lombok.*; +import Application.Models.Enums.HairColor; +import Application.Models.Enums.Sex; +import Application.Models.Utils.IdGenerator; + +import java.util.ArrayList; + +/** + * Класс, представляющий пользователя системы. + * Хранит информацию о пользователе, включая личные данные, список банковских счетов и друзей. + */ +@Getter +@Setter +public class User { + private Integer id; + + private String login; + + private String name; + + private Integer age; + + private Sex sex; + + private HairColor hairType; + + private ArrayList bankAccounts = new ArrayList<>(); + + private ArrayList friends = new ArrayList<>(); + + /** + * Конструктор для создания нового пользователя. + * Генерирует уникальный идентификатор для пользователя и инициализирует его данные. + * + * @param idGenerator генератор ID для создания уникального идентификатора пользователя. + * @param login логин пользователя. + * @param name имя пользователя. + * @param age возраст пользователя. + * @param sex пол пользователя. + * @param hairType цвет волос пользователя. + */ + public User( + IdGenerator idGenerator, + String login, + String name, + Integer age, + Sex sex, + HairColor hairType + ) { + this.id = idGenerator.generateUserId(); + this.login = login; + this.name = name; + this.age = age; + this.sex = sex; + this.hairType = hairType; + this.bankAccounts = bankAccounts != null ? bankAccounts : new ArrayList<>(); + this.friends = friends != null ? friends : new ArrayList<>(); + } +} diff --git a/Application/src/main/java/Application/Models/Enums/HairColor.java b/Application/src/main/java/Application/Models/Enums/HairColor.java new file mode 100644 index 0000000..b1768fb --- /dev/null +++ b/Application/src/main/java/Application/Models/Enums/HairColor.java @@ -0,0 +1,17 @@ +package Application.Models.Enums; + +/** + * Перечисление возможных цветов волос пользователя. + */ +public enum HairColor { + Blond, + Ash, + Brown, + Auburn, + Black, + Dyed, + Colored, + Grey, + White, + Bold +} diff --git a/Application/src/main/java/Application/Models/Enums/OperationType.java b/Application/src/main/java/Application/Models/Enums/OperationType.java new file mode 100644 index 0000000..a11cee8 --- /dev/null +++ b/Application/src/main/java/Application/Models/Enums/OperationType.java @@ -0,0 +1,11 @@ +package Application.Models.Enums; + +/** + * Перечисление возможных типов операций с банковским счётом. + */ +public enum OperationType { + Deposit, + Withdraw, + Transfer, + CheckBalance +} diff --git a/Application/src/main/java/Application/Models/Enums/Sex.java b/Application/src/main/java/Application/Models/Enums/Sex.java new file mode 100644 index 0000000..3ab3aac --- /dev/null +++ b/Application/src/main/java/Application/Models/Enums/Sex.java @@ -0,0 +1,10 @@ +package Application.Models.Enums; + +/** + * Перечисление возможных вариантов пола пользователя. + */ +public enum Sex { + Undefined, + Male, + Female +} diff --git a/Application/src/main/java/Application/Models/Utils/IdGenerator.java b/Application/src/main/java/Application/Models/Utils/IdGenerator.java new file mode 100644 index 0000000..e461b94 --- /dev/null +++ b/Application/src/main/java/Application/Models/Utils/IdGenerator.java @@ -0,0 +1,31 @@ +package Application.Models.Utils; + +/** + * Класс для генерации уникальных Id пользователей и банковских счетов + */ +public class IdGenerator { + private int userId = 0; + private int bankAccountId = 0; + + /** + * Генерирует уникальный идентификатор пользователя. + * Каждый вызов метода увеличивает текущий userId на 1 и возвращает новое значение. + * Метод синхронизирован для обеспечения корректности работы в многозадачной среде. + * + * @return новый уникальный идентификатор пользователя. + */ + public synchronized int generateUserId() { + return ++userId; + } + + /** + * Генерирует уникальный идентификатор банковского счета. + * Каждый вызов метода увеличивает текущий bankAccountId на 1 и возвращает новое значение. + * Метод синхронизирован для обеспечения корректности работы в многозадачной среде. + * + * @return новый уникальный идентификатор банковского счета. + */ + public synchronized int generateBankAccountId() { + return ++bankAccountId; + } +} diff --git a/Application/src/main/java/Application/Services/UserService.java b/Application/src/main/java/Application/Services/UserService.java new file mode 100644 index 0000000..282a16d --- /dev/null +++ b/Application/src/main/java/Application/Services/UserService.java @@ -0,0 +1,228 @@ +package Application.Services; + +import lombok.AllArgsConstructor; +import Application.Abstractions.Repositories.IBankAccountRepository; +import Application.Abstractions.Repositories.IOperationRepository; +import Application.Abstractions.Repositories.IUserRepository; +import Application.Contracts.Interfaces.IUserService; +import Application.Contracts.ResultTypes.BankAccountResult; +import Application.Contracts.ResultTypes.OperationResult; +import Application.Contracts.ResultTypes.UserResult; +import Application.Managers.UserManager; +import Application.Models.Entites.BankAccount; +import Application.Models.Entites.Operation; +import Application.Models.Entites.User; +import Application.Models.Enums.OperationType; +import lombok.Getter; + +/** + * Сервис для управления пользователями, их банковскими счетами и операциями. + * Взаимодействует с репозиториями пользователей, банковских счетов и операций. + * Обрабатывает запросы, такие как создание/удаление пользователей, переводы, операции с балансом и так далее. + */ +@AllArgsConstructor +public class UserService implements IUserService { + + @Getter + private IUserRepository _userRepository; + + @Getter + private IBankAccountRepository _bankAccountRepository; + + @Getter + private IOperationRepository _operationRepository; + + private UserManager _userManager; + + /** + * Создает нового пользователя. + * + * @param user объект пользователя, который нужно добавить. + * @return result-type добавления пользователя. + */ + @Override + public UserResult CreateUser(User user) { + return _userRepository.AddUser(user); + } + + /** + * Удаляет существующего пользователя. + * + * @param user объект пользователя, которого нужно удалить. + * @return result-type удаления пользователя. + */ + @Override + public UserResult DeleteUser(User user) { + return _userRepository.DeleteUser(user.getId()); + } + + /** + * Получает информацию о пользователе и выводит ее. + * + * @param user объект пользователя, информацию о котором нужно вывести. + */ + @Override + public void GetUserInfo(User user) { + _userManager.GetUserInfo(user); + } + + /** + * Добавляет другого пользователя в список друзей. + * + * @param user текущий пользователь, добавляющий друга. + * @param other пользователь, который будет добавлен в друзья. + */ + @Override + public void AddFriend(User user, User other) { + _userManager.AddFriend(user, other); + } + + /** + * Удаляет пользователя из списка друзей. + * + * @param user текущий пользователь, удаляющий друга. + * @param other пользователь, которого нужно удалить из друзей. + */ + @Override + public void RemoveFriend(User user, User other) { + _userManager.RemoveFriend(user, other); + } + + /** + * Добавляет новый банковский счет пользователю. + * + * @param user пользователь, которому добавляется банковский счет. + * @param bankAccount объект банковского счета, который нужно добавить. + * @return result-type добавления счета. + */ + @Override + public BankAccountResult addBankAccount(User user, BankAccount bankAccount) { + _userManager.AddBankAccount(user, bankAccount); + return _bankAccountRepository.AddBankAccount(bankAccount); + } + + /** + * Удаляет банковский счет у пользователя. + * + * @param user пользователь, у которого нужно удалить банковский счет. + * @param bankAccount объект банковского счета, который нужно удалить. + * @return result-type удаления счета. + */ + @Override + public BankAccountResult RemoveBankAccount(User user, BankAccount bankAccount) { + _userManager.RemoveBankAccount(user, bankAccount); + return _bankAccountRepository.DeleteBankAccount(bankAccount.getId()); + } + + /** + * Проверяет баланс на банковском счете пользователя. + * + * @param user пользователь, чьи средства нужно проверить. + * @param bankAccount объект банковского счета, на котором нужно проверить баланс. + * @return result-type операции (успех или ошибка). + */ + @Override + public OperationResult CheckBalance(User user, BankAccount bankAccount) { + _userManager.CheckBalance(user, bankAccount); + return _operationRepository.AddOperation(new Operation(bankAccount.getId(), OperationType.CheckBalance, 0.0)); + } + + /** + * Пополняет банковский счет на указанную сумму. + * + * @param bankAccount объект банковского счета, на который нужно пополнить средства. + * @param amount сумма пополнения. + * @return result-type операции (успех или ошибка). + */ + @Override + public OperationResult Deposit(BankAccount bankAccount, Double amount) { + var account = _bankAccountRepository.FindBankAccountById(bankAccount.getId()); + _bankAccountRepository.UpdateBankAccountBalance(account.getId(), account.getBalance() + amount); + return _operationRepository.AddOperation(new Operation(bankAccount.getId(), OperationType.Deposit, amount)); + } + + /** + * Снимает средства с банковского счета. + * + * @param bankAccount объект банковского счета, с которого нужно снять деньги. + * @param amount сумма снятия. + * @return result-type операции (успех или ошибка). + */ + @Override + public OperationResult Withdraw(BankAccount bankAccount, Double amount) { + var account = _bankAccountRepository.FindBankAccountById(bankAccount.getId()); + if (account.getBalance() - amount >= 0) { + _bankAccountRepository.UpdateBankAccountBalance(account.getId(), account.getBalance() - amount); + return _operationRepository.AddOperation(new Operation(bankAccount.getId(), OperationType.Withdraw, amount)); + } + return new OperationResult.OperationError("Not enough balance"); + } + + /** + * Переводит средства между двумя банковскими счетами. + * В зависимости от типа отношений между пользователями применяется комиссия. + * + * @param bankAccount1 первый банковский счет (откуда переводятся деньги). + * @param bankAccount2 второй банковский счет (куда переводятся деньги). + * @param amount сумма перевода. + * @return result-type операции (успех или ошибка). + */ + @Override + public OperationResult Transfer(BankAccount bankAccount1, BankAccount bankAccount2, Double amount) { + if (amount == null || amount <= 0) { + return new OperationResult.OperationError("Invalid transfer amount."); + } + + var account1 = _bankAccountRepository.FindBankAccountById(bankAccount1.getId()); + var account2 = _bankAccountRepository.FindBankAccountById(bankAccount2.getId()); + + if (account1 == null || account2 == null) { + return new OperationResult.OperationError("One or both bank accounts not found."); + } + + var user1 = _userRepository.FindUserById(account1.getUserId()); + var user2 = _userRepository.FindUserById(account2.getUserId()); + + if (user1 == null || user2 == null) { + return new OperationResult.OperationError("One or both users not found."); + } + + double commissionRate; + + if (account1.getUserId().equals(account2.getUserId())) { + commissionRate = 0.00; + } else if (user1.getFriends().stream().anyMatch(friend -> friend.getId().equals(user2.getId()))) { + commissionRate = 0.03; + } else { + commissionRate = 0.10; + } + + double commission = amount * commissionRate; + double totalAmount = amount + commission; + + if (account1.getBalance() < totalAmount) { + return new OperationResult.OperationError("Insufficient funds, including commission."); + } + + _bankAccountRepository.UpdateBankAccountBalance(account1.getId(), account1.getBalance() - totalAmount); + _bankAccountRepository.UpdateBankAccountBalance(account2.getId(), account2.getBalance() + amount); + + _operationRepository.AddOperation(new Operation(bankAccount1.getId(), OperationType.Transfer, totalAmount)); + _operationRepository.AddOperation(new Operation(bankAccount2.getId(), OperationType.Deposit, amount)); + + return new OperationResult.Success(); + } + + /** + * Получает историю операций по банковскому счету. + * + * @param bankAccount объект банковского счета, для которого нужно получить историю операций. + * @return result-type с выводом историей операций в консоль. + */ + @Override + public OperationResult GetOperationHistory(BankAccount bankAccount) { + var account = _bankAccountRepository.FindBankAccountById(bankAccount.getId()); + var operations = _operationRepository.GetOperationHistory(account.getId()); + return _userManager.PrintHistory(account, operations); + } +} diff --git a/DataAccess/pom.xml b/DataAccess/pom.xml new file mode 100644 index 0000000..ec4f99c --- /dev/null +++ b/DataAccess/pom.xml @@ -0,0 +1,125 @@ + + + 4.0.0 + + is.technologies + DataAccess + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + + + + + + + org.projectlombok + lombok + 1.18.30 + provided + + + + is.technologies + Application + 1.0-SNAPSHOT + + + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + + ${project.build.directory}/libs + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + true + libs/ + + is.technologies.Main + + + + + + + + + org.apache.maven.plugins + maven-site-plugin + 3.12.1 + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 3.4.2 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.21.0 + + + org.junit.jupiter + junit-jupiter-engine + 5.9.2 + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.0 + + 17 + ${java.home}/bin/javadoc + + + + maven-javadocs + + jar + + + + + + + + \ No newline at end of file diff --git a/DataAccess/src/main/java/DataAccess/BankAccountRepository.java b/DataAccess/src/main/java/DataAccess/BankAccountRepository.java new file mode 100644 index 0000000..c04979e --- /dev/null +++ b/DataAccess/src/main/java/DataAccess/BankAccountRepository.java @@ -0,0 +1,99 @@ +package DataAccess; + +import lombok.NoArgsConstructor; +import Application.Abstractions.Repositories.IBankAccountRepository; +import Application.Contracts.ResultTypes.BankAccountResult; +import Application.Models.Entites.BankAccount; + +import java.util.ArrayList; +import java.util.Objects; + +/** + * Репозиторий для управления банковскими счетами. + * Реализует интерфейс {@link IBankAccountRepository} и выполняет CRUD-операции с объектами {@link BankAccount}. + * + *

Хранение банковских счетов осуществляется в памяти с использованием {@link ArrayList}.

+ */ +@NoArgsConstructor +public class BankAccountRepository implements IBankAccountRepository { + + /** + * Внутреннее хранилище банковских счетов в памяти. + */ + private final ArrayList _bankAccounts = new ArrayList<>(); + + /** + * Добавляет новый банковский счет в хранилище. + * + * @param account объект банковского счета, который будет добавлен. + * @return {@link BankAccountResult.Success} при успешном добавлении + * или {@link BankAccountResult.BankAccountCreationError} в случае ошибки. + */ + @Override + public BankAccountResult AddBankAccount(BankAccount account) { + if (account == null) { + return new BankAccountResult.BankAccountCreationError("Bank account cannot be null"); + } + _bankAccounts.add(account); + return new BankAccountResult.Success(); + } + + /** + * Ищет банковский счет по идентификатору. + * + * @param id идентификатор банковского счета. + * @return объект {@link BankAccount}, если найден, иначе {@code null}. + */ + @Override + public BankAccount FindBankAccountById(Integer id) { + if (id < 0) { + return null; + } + for (BankAccount account : _bankAccounts) { + if (Objects.equals(account.getId(), id)) { + return account; + } + } + return null; + } + + /** + * Обновляет баланс банковского счета. + * + * @param id идентификатор банковского счета. + * @param balance новый баланс счета. + * @return {@link BankAccountResult.Success} при успешном обновлении + * или {@link BankAccountResult.BankAccountUpdateError} в случае ошибки. + */ + @Override + public BankAccountResult UpdateBankAccountBalance(Integer id, Double balance) { + if (id < 0 || balance < 0) { + return new BankAccountResult.BankAccountUpdateError("Invalid update parameters"); + } + + for (BankAccount account : _bankAccounts) { + if (Objects.equals(account.getId(), id)) { + account.setBalance(balance); + return new BankAccountResult.Success(); + } + } + + return new BankAccountResult.BankAccountUpdateError("Bank account balance update failed"); + } + + /** + * Удаляет банковский счет по идентификатору. + * + * @param id идентификатор банковского счета, который нужно удалить. + * @return {@link BankAccountResult.Success} при успешном удалении + * или {@link BankAccountResult.BankAccountDeletionError} в случае ошибки. + */ + @Override + public BankAccountResult DeleteBankAccount(Integer id) { + if (id < 0) { + return new BankAccountResult.BankAccountDeletionError("Invalid delete parameters"); + } + _bankAccounts.removeIf(bankAccount -> Objects.equals(bankAccount.getId(), id)); + return new BankAccountResult.Success(); + } +} diff --git a/DataAccess/src/main/java/DataAccess/OperationRepository.java b/DataAccess/src/main/java/DataAccess/OperationRepository.java new file mode 100644 index 0000000..589f474 --- /dev/null +++ b/DataAccess/src/main/java/DataAccess/OperationRepository.java @@ -0,0 +1,50 @@ +package DataAccess; + +import lombok.NoArgsConstructor; +import Application.Abstractions.Repositories.IOperationRepository; +import Application.Contracts.ResultTypes.OperationResult; +import Application.Models.Entites.Operation; + +import java.util.ArrayList; + +/** + * Репозиторий для управления операциями банковских счетов. + * Реализует интерфейс {@link IOperationRepository} и выполняет операции добавления и получения истории операций. + * + *

Хранение операций осуществляется в памяти с использованием {@link ArrayList}.

+ */ +@NoArgsConstructor +public class OperationRepository implements IOperationRepository { + + /** + * Внутреннее хранилище операций в памяти. + */ + private final ArrayList operations = new ArrayList<>(); + + /** + * Добавляет новую операцию в хранилище. + * + * @param operation объект операции, который будет добавлен. + * @return результат операции добавления: {@link OperationResult.Success} при успешном добавлении + * или {@link OperationResult.OperationError} в случае ошибки. + */ + @Override + public OperationResult AddOperation(Operation operation) { + if (operation == null) { + return new OperationResult.OperationError("Operation can not be null"); + } + operations.add(operation); + return new OperationResult.Success(); + } + + /** + * Возвращает историю операций для указанного идентификатора банковского счета. + * + * @param bankAccountId идентификатор банковского счета, для которого требуется история операций. + * @return список операций {@link ArrayList} связанных с банковским счетом. + */ + @Override + public ArrayList GetOperationHistory(Integer bankAccountId) { + return operations; + } +} diff --git a/DataAccess/src/main/java/DataAccess/UserRepository.java b/DataAccess/src/main/java/DataAccess/UserRepository.java new file mode 100644 index 0000000..8cd18c2 --- /dev/null +++ b/DataAccess/src/main/java/DataAccess/UserRepository.java @@ -0,0 +1,94 @@ +package DataAccess; + +import lombok.NoArgsConstructor; +import Application.Abstractions.Repositories.IUserRepository; +import Application.Contracts.ResultTypes.UserResult; +import Application.Models.Entites.User; + +import java.util.ArrayList; +import java.util.Objects; + +/** + * Реализация репозитория для управления пользователями. + * Хранит пользователей в памяти (в списке) и реализует операции CRUD для сущности {@link User}. + * + *

Этот класс использует {@link ArrayList} для хранения данных и позволяет добавлять, обновлять, искать и удалять пользователей.

+ */ +@NoArgsConstructor +public class UserRepository implements IUserRepository { + + private final ArrayList _users = new ArrayList<>(); + + /** + * Добавляет нового пользователя в хранилище. + * + * @param user объект пользователя, который будет добавлен. + * @return результат операции добавления, может быть ошибка создания пользователя, если пользователь равен {@code null}. + */ + @Override + public UserResult AddUser(User user) { + if (user == null) { + return new UserResult.UserCreationError("User can not be null"); + } + _users.add(user); + return new UserResult.Success(); + } + + /** + * Находит пользователя по его идентификатору. + * + * @param id идентификатор пользователя, которого нужно найти. + * @return найденный пользователь или {@code null}, если пользователь с таким идентификатором не существует. + */ + @Override + public User FindUserById(Integer id) { + if (id < 0) { + return null; + } + for (User user : _users) { + if (Objects.equals(user.getId(), id)) { + return user; + } + } + return null; + } + + /** + * Обновляет данные пользователя по его идентификатору. + * + * @param id идентификатор пользователя, которого нужно обновить. + * @param userUpdate объект с новыми данными пользователя. + * @return результат операции обновления, может быть ошибка, если параметры обновления неверны. + */ + @Override + public UserResult UpdateUser(Integer id, User userUpdate) { + if (userUpdate == null || id < 0) { + return new UserResult.UserUpdateError("Invalid update parameters"); + } + + for (int i = 0; i < _users.size(); ++i) { + User existingUser = _users.get(i); + if (Objects.equals(existingUser.getId(), id)) { + _users.set(i, userUpdate); + return new UserResult.Success(); + } + } + + return new UserResult.UserUpdateError("User update failed "); + } + + /** + * Удаляет пользователя по его идентификатору. + * + * @param id идентификатор пользователя, которого нужно удалить. + * @return результат операции удаления, может быть ошибка, если параметры удаления неверны. + */ + @Override + public UserResult DeleteUser(Integer id) { + if (id < 0) { + return new UserResult.UserDeletionError("Invalid delete parameters"); + } + _users.removeIf(user -> Objects.equals(user.getId(), id)); + return new UserResult.Success(); + } +} diff --git a/Presentation/pom.xml b/Presentation/pom.xml new file mode 100644 index 0000000..e799d3e --- /dev/null +++ b/Presentation/pom.xml @@ -0,0 +1,152 @@ + + + 4.0.0 + + is.technologies + Presentation + 1.0-SNAPSHOT + + + 17 + 17 + UTF-8 + + + + + + org.junit.jupiter + junit-jupiter-api + 5.9.2 + test + + + + org.junit.jupiter + junit-jupiter-engine + 5.9.2 + test + + + + + org.projectlombok + lombok + 1.18.30 + provided + + + + is.technologies + Application + 1.0-SNAPSHOT + + + + is.technologies + DataAccess + 1.0-SNAPSHOT + + + + org.mockito + mockito-core + 3.0.0 + test + + + + + + + + + + + org.apache.maven.plugins + maven-dependency-plugin + + + copy-dependencies + prepare-package + + copy-dependencies + + + + ${project.build.directory}/libs + + + + + + + + + org.apache.maven.plugins + maven-jar-plugin + 3.3.0 + + + + true + libs/ + + is.technologies.Main + + + + + + + + + org.apache.maven.plugins + maven-site-plugin + 3.12.1 + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 3.4.2 + + + + org.apache.maven.plugins + maven-surefire-plugin + 2.21.0 + + + org.junit.jupiter + junit-jupiter-engine + 5.9.2 + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.0 + + 17 + ${java.home}/bin/javadoc + + + + maven-javadocs + + jar + + + + + + + + \ No newline at end of file diff --git a/Presentation/src/main/java/Presentation/Console/Main.java b/Presentation/src/main/java/Presentation/Console/Main.java new file mode 100644 index 0000000..5047091 --- /dev/null +++ b/Presentation/src/main/java/Presentation/Console/Main.java @@ -0,0 +1,11 @@ +package Presentation.Console; + + +import Presentation.Interfaces.IMenu; + +public class Main { + public static void main(String[] args) { + IMenu menu = new Menu(); + menu.Run(); + } +} diff --git a/Presentation/src/main/java/Presentation/Console/Menu.java b/Presentation/src/main/java/Presentation/Console/Menu.java new file mode 100644 index 0000000..ed7ce7f --- /dev/null +++ b/Presentation/src/main/java/Presentation/Console/Menu.java @@ -0,0 +1,326 @@ +package Presentation.Console; + +import Application.Contracts.ResultTypes.BankAccountResult; +import Application.Contracts.ResultTypes.OperationResult; +import Application.Contracts.ResultTypes.UserResult; +import Application.Managers.UserManager; +import Application.Models.Entites.BankAccount; +import Application.Models.Entites.User; +import Application.Models.Enums.HairColor; +import Application.Models.Enums.Sex; +import Application.Models.Utils.IdGenerator; +import Application.Services.UserService; +import Presentation.Interfaces.IMenu; +import DataAccess.BankAccountRepository; +import DataAccess.OperationRepository; +import DataAccess.UserRepository; + +import java.util.Scanner; + +/** + * Класс {@code Menu} представляет консольное меню для управления пользователями и банковскими счетами. + * Предоставляет интерфейс для создания пользователей, управления друзьями, работы с банковскими счетами + * и выполнения финансовых операций. + *

+ * Реализует интерфейс {@link IMenu}. + *

+ * Основные возможности: + *

    + *
  • Создание пользователя
  • + *
  • Просмотр информации о пользователе
  • + *
  • Управление списком друзей пользователя
  • + *
  • Создание банковского счета
  • + *
  • Проверка баланса счета
  • + *
  • Снятие и пополнение средств
  • + *
  • Перевод средств между счетами
  • + *
+ * + * Зависимости: + *
    + *
  • {@link UserService} - основной сервис для работы с пользователями и счетами
  • + *
  • {@link Scanner} - для считывания ввода пользователя
  • + *
+ * + * @author lim0sha + * @version 1.0 + */ +public class Menu implements IMenu { + + private final IdGenerator userIdGenerator = new IdGenerator(); + private final IdGenerator bankAccountIdGenerator = new IdGenerator(); + private final UserService userService = new UserService( + new UserRepository(), + new BankAccountRepository(), + new OperationRepository(), + new UserManager()); + + private final Scanner scanner = new Scanner(System.in); + + /** + * Запускает основное меню и обрабатывает выбор пользователя. + * Предоставляет доступ к основным функциям системы через консольный интерфейс. + */ + @Override + public void Run() { + while (true) { + System.out.println("\n--- Меню ---"); + System.out.println("1. Создать пользователя"); + System.out.println("2. Показать информацию о пользователе"); + System.out.println("3. Изменить список друзей пользователя"); + System.out.println("4. Создать счет пользователя"); + System.out.println("5. Просмотреть баланс счета"); + System.out.println("6. Снять деньги со счета"); + System.out.println("7. Пополнить счет"); + System.out.println("8. Перевести деньги"); + System.out.println("0. Выйти"); + System.out.print("Выберите команду: "); + + int choice = scanner.nextInt(); + scanner.nextLine(); + + switch (choice) { + case 1 -> createUser(); + case 2 -> getUserInfo(); + case 3 -> manageFriends(); + case 4 -> createBankAccount(); + case 5 -> checkBalance(); + case 6 -> withdraw(); + case 7 -> deposit(); + case 8 -> transfer(); + case 0 -> { + System.out.println("Выход..."); + return; + } + default -> System.out.println("Неверная команда!"); + } + } + } + + /** + * Создает нового пользователя с вводом данных через консоль. + */ + private void createUser() { + System.out.print("Введите логин: "); + String login = scanner.nextLine(); + System.out.print("Введите имя: "); + String name = scanner.nextLine(); + System.out.print("Введите возраст: "); + int age = scanner.nextInt(); + scanner.nextLine(); + + + System.out.println("Выберите пол:"); + System.out.println("1. Мужской"); + System.out.println("2. Женский"); + System.out.println("3. Неопределённый"); + System.out.print("Введите цифру (1-3): "); + int sexChoice = scanner.nextInt(); + scanner.nextLine(); + + Sex sex = switch (sexChoice) { + case 1 -> Sex.Male; + case 2 -> Sex.Female; + default -> Sex.Undefined; + }; + + + System.out.println("Выберите цвет волос:"); + System.out.println("1. Блонд"); + System.out.println("2. Пепельный"); + System.out.println("3. Каштановый"); + System.out.println("4. Рыжий"); + System.out.println("5. Черный"); + System.out.println("6. Окрашенный"); + System.out.println("7. Цветной"); + System.out.println("8. Седой"); + System.out.println("9. Белый"); + System.out.println("10. Лысый"); + System.out.print("Введите цифру (1-10): "); + int hairChoice = scanner.nextInt(); + scanner.nextLine(); + + HairColor hairColor = switch (hairChoice) { + case 1 -> HairColor.Blond; + case 2 -> HairColor.Ash; + case 3 -> HairColor.Brown; + case 4 -> HairColor.Auburn; + case 5 -> HairColor.Black; + case 6 -> HairColor.Dyed; + case 7 -> HairColor.Colored; + case 8 -> HairColor.Grey; + case 9 -> HairColor.White; + default -> HairColor.Bold; + }; + + User user = new User(userIdGenerator, login, name, age, sex, hairColor); + UserResult result = userService.CreateUser(user); + + System.out.println(result instanceof UserResult.Success ? "Пользователь создан!" : "Ошибка создания пользователя."); + } + + /** + * Выводит информацию о пользователе по введенному ID. + */ + private void getUserInfo() { + System.out.print("Введите ID пользователя: "); + int userId = scanner.nextInt(); + User user = userService.get_userRepository().FindUserById(userId); + if (user != null) { + userService.GetUserInfo(user); + } else { + System.out.println("Пользователь не найден."); + } + } + + /** + * Позволяет добавить или удалить друга из списка друзей пользователя. + */ + private void manageFriends() { + System.out.print("Введите ID пользователя: "); + int userId = scanner.nextInt(); + System.out.print("Введите ID друга: "); + int friendId = scanner.nextInt(); + + User user = userService.get_userRepository().FindUserById(userId); + User friend = userService.get_userRepository().FindUserById(friendId); + + if (user != null && friend != null) { + System.out.print("Добавить друга (1) или удалить (2): "); + int action = scanner.nextInt(); + + if (action == 1) { + userService.AddFriend(user, friend); + System.out.println("Друг добавлен."); + } else if (action == 2) { + userService.RemoveFriend(user, friend); + System.out.println("Друг удален."); + } else { + System.out.println("Неверная команда."); + } + } else { + System.out.println("Пользователь или друг не найден."); + } + } + + /** + * Создает банковский счет для существующего пользователя. + */ + private void createBankAccount() { + System.out.print("Введите ID пользователя: "); + int userId = scanner.nextInt(); + + User user = userService.get_userRepository().FindUserById(userId); + if (user == null) { + System.out.println("Пользователь не найден."); + return; + } + + System.out.println("Найден пользователь: " + user.getName() + " (ID: " + user.getId() + ")"); + + BankAccount account = new BankAccount(bankAccountIdGenerator, user); + BankAccountResult result = userService.addBankAccount(user, account); + + if (result instanceof BankAccountResult.Success) { + System.out.println("Счет создан!"); + } else { + System.out.println("Ошибка создания счета."); + } + } + + /** + * Проверяет баланс на указанном банковском счете. + */ + private void checkBalance() { + System.out.print("Введите ID счета: "); + int accountId = scanner.nextInt(); + BankAccount account = userService.get_bankAccountRepository().FindBankAccountById(accountId); + + if (account != null) { + User user = userService.get_userRepository().FindUserById(account.getUserId()); + if (user != null) { + userService.CheckBalance(user, account); + } else { + System.out.println("Пользователь не найден."); + } + } else { + System.out.println("Счет не найден."); + } + } + + /** + * Снимает средства с указанного банковского счета. + */ + private void withdraw() { + System.out.print("Введите ID счета: "); + int accountId = scanner.nextInt(); + System.out.print("Введите сумму снятия: "); + double amount = scanner.nextDouble(); + + BankAccount account = userService.get_bankAccountRepository().FindBankAccountById(accountId); + if (account != null) { + OperationResult result = userService.Withdraw(account, amount); + + if (result instanceof OperationResult.Success) { + System.out.println("Деньги сняты."); + } else if (result instanceof OperationResult.OperationError error) { + System.out.println("Ошибка: " + error.getMessage()); + } + } else { + System.out.println("Счет не найден."); + } + } + + /** + * Пополняет баланс указанного банковского счета. + */ + private void deposit() { + System.out.print("Введите ID счета: "); + int accountId = scanner.nextInt(); + System.out.print("Введите сумму пополнения: "); + double amount = scanner.nextDouble(); + + BankAccount account = userService.get_bankAccountRepository().FindBankAccountById(accountId); + if (account != null) { + OperationResult result = userService.Deposit(account, amount); + if (result instanceof OperationResult.Success) { + System.out.println("Счет пополнен."); + } else if (result instanceof OperationResult.OperationError error) { + System.out.println("Ошибка: " + error.getMessage()); + } + } else { + System.out.println("Счет не найден."); + } + } + + /** + * Переводит средства с одного банковского счета на другой. + */ + private void transfer() { + try { + System.out.print("Введите ID счета отправителя: "); + int fromId = Integer.parseInt(scanner.nextLine().trim()); + + System.out.print("Введите ID счета получателя: "); + int toId = Integer.parseInt(scanner.nextLine().trim()); + + System.out.print("Введите сумму перевода: "); + double amount = Double.parseDouble(scanner.nextLine().trim().replace(',', '.')); + + BankAccount fromAccount = userService.get_bankAccountRepository().FindBankAccountById(fromId); + BankAccount toAccount = userService.get_bankAccountRepository().FindBankAccountById(toId); + + if (fromAccount != null && toAccount != null) { + OperationResult result = userService.Transfer(fromAccount, toAccount, amount); + if (result instanceof OperationResult.Success) { + System.out.println("Перевод выполнен."); + } else if (result instanceof OperationResult.OperationError error) { + System.out.println("Ошибка: " + error.getMessage()); + } + } else { + System.out.println("Один или оба счета не найдены."); + } + } catch (NumberFormatException e) { + System.out.println("Ошибка ввода! Пожалуйста, введите корректные числовые значения."); + } + } +} diff --git a/Presentation/src/main/java/Presentation/Interfaces/IMenu.java b/Presentation/src/main/java/Presentation/Interfaces/IMenu.java new file mode 100644 index 0000000..592e4d8 --- /dev/null +++ b/Presentation/src/main/java/Presentation/Interfaces/IMenu.java @@ -0,0 +1,14 @@ +package Presentation.Interfaces; + +/** + * Интерфейс для меню пользовательского интерфейса в консоли. + * Обеспечивает базовый контракт для запуска меню. + */ +public interface IMenu { + + /** + * Запускает отображение и обработку логики меню. + * Отображает доступные опции и обрабатывает пользовательский ввод. + */ + void Run(); +} diff --git a/Presentation/src/test/java/BankTests.java b/Presentation/src/test/java/BankTests.java new file mode 100644 index 0000000..586778f --- /dev/null +++ b/Presentation/src/test/java/BankTests.java @@ -0,0 +1,102 @@ +import Application.Abstractions.Repositories.IBankAccountRepository; +import Application.Abstractions.Repositories.IOperationRepository; +import Application.Contracts.ResultTypes.OperationResult; +import Application.Models.Entites.BankAccount; +import Application.Models.Entites.User; +import Application.Models.Enums.HairColor; +import Application.Models.Enums.Sex; +import Application.Models.Utils.IdGenerator; +import Application.Services.UserService; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertInstanceOf; +import static org.mockito.Mockito.*; + +public class BankTests { + + @Mock + private IBankAccountRepository bankAccountRepository; + + @Mock + private IOperationRepository operationRepository; + + @InjectMocks + private UserService userService; + + private BankAccount bankAccount; + + @BeforeEach + void setUp() { + MockitoAnnotations.initMocks(this); + User user = new User(new IdGenerator(), "lim0sha", "Sasha", 22, Sex.Male, HairColor.Brown); + bankAccount = new BankAccount(new IdGenerator(), user); + bankAccount.setBalance(100.0); + } + + @Test + void testWithdrawWithSufficientBalance() { + Double withdrawAmount = 50.0; + Double initialBalance = bankAccount.getBalance(); + + when(bankAccountRepository.FindBankAccountById(bankAccount.getId())).thenReturn(bankAccount); + when(bankAccountRepository.UpdateBankAccountBalance(bankAccount.getId(), initialBalance - withdrawAmount)) + .thenAnswer(invocation -> { + bankAccount.setBalance(initialBalance - withdrawAmount); + return null; + }); + when(operationRepository.AddOperation(any())).thenReturn(new OperationResult.Success()); + + OperationResult operationResult = userService.Withdraw(bankAccount, withdrawAmount); + + assertInstanceOf(OperationResult.Success.class, operationResult); + assertEquals(initialBalance - withdrawAmount, bankAccount.getBalance(), 0.001); + verify(bankAccountRepository, times(1)).UpdateBankAccountBalance(bankAccount.getId(), initialBalance - withdrawAmount); + verify(operationRepository, times(1)).AddOperation(any()); + + assertEquals(50.0, bankAccount.getBalance(), 0.001); + } + + @Test + void testWithdrawWithInsufficientBalance() { + Double withdrawAmount = 150.0; + + when(bankAccountRepository.FindBankAccountById(bankAccount.getId())).thenReturn(bankAccount); + + OperationResult operationResult = userService.Withdraw(bankAccount, withdrawAmount); + + assertInstanceOf(OperationResult.OperationError.class, operationResult); + assertEquals("Not enough balance", ((OperationResult.OperationError) operationResult).getMessage()); + verify(bankAccountRepository, times(0)).UpdateBankAccountBalance(any(), anyDouble()); + verify(operationRepository, times(0)).AddOperation(any()); + + assertEquals(100.0, bankAccount.getBalance(), 0.001); + } + + @Test + void testDeposit() { + Double depositAmount = 100.0; + Double initialBalance = bankAccount.getBalance(); + + when(bankAccountRepository.FindBankAccountById(bankAccount.getId())).thenReturn(bankAccount); + when(bankAccountRepository.UpdateBankAccountBalance(bankAccount.getId(), initialBalance + depositAmount)) + .thenAnswer(invocation -> { + bankAccount.setBalance(initialBalance + depositAmount); + return null; + }); + when(operationRepository.AddOperation(any())).thenReturn(new OperationResult.Success()); + + OperationResult operationResult = userService.Deposit(bankAccount, depositAmount); + + assertInstanceOf(OperationResult.Success.class, operationResult); + assertEquals(initialBalance + depositAmount, bankAccount.getBalance(), 0.001); + verify(bankAccountRepository, times(1)).UpdateBankAccountBalance(bankAccount.getId(), initialBalance + depositAmount); + verify(operationRepository, times(1)).AddOperation(any()); + + assertEquals(200.0, bankAccount.getBalance(), 0.001); + } +} \ No newline at end of file diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..0223449 --- /dev/null +++ b/pom.xml @@ -0,0 +1,33 @@ + + 4.0.0 + com.example + lim0sha + 1.0-SNAPSHOT + pom + + + Application + DataAccess + Presentation + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.4.1 + + + package + + javadoc + + + + + + + \ No newline at end of file