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