diff --git a/.gitignore b/.gitignore index b63da45..5f90047 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,7 @@ build/ !**/src/test/**/build/ ### IntelliJ IDEA ### +./.idea .idea/modules.xml .idea/jarRepositories.xml .idea/compiler.xml diff --git a/.idea/.gitignore b/.idea/.gitignore new file mode 100644 index 0000000..13566b8 --- /dev/null +++ b/.idea/.gitignore @@ -0,0 +1,8 @@ +# Default ignored files +/shelf/ +/workspace.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..0194542 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +features \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..d7be335 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..4b2a88c --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..2b63946 --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000..c106d17 --- /dev/null +++ b/build.gradle @@ -0,0 +1,66 @@ +plugins { + id 'java' + id 'application' +} + +group = 'org.lab' +version = '1.0-SNAPSHOT' + + +repositories { + mavenCentral() +} + +dependencies { + + + testImplementation platform('org.junit:junit-bom:5.10.0') + testImplementation 'org.junit.jupiter:junit-jupiter' + testRuntimeOnly 'org.junit.platform:junit-platform-launcher' +} + +application { + + mainClass = 'Main' + + applicationDefaultJvmArgs = [ + '-Dfile.encoding=UTF-8', + '-Dsun.stdout.encoding=UTF-8', + '-Dsun.stderr.encoding=UTF-8', + '-Dconsole.encoding=UTF-8', + ] +} + +java { + toolchain { + languageVersion = JavaLanguageVersion.of(21) + } +} + +tasks.withType(JavaCompile).configureEach { + options.compilerArgs += ['-Xlint:preview', '--enable-preview'] +} + +tasks.withType(JavaExec).configureEach { + jvmArgs += '--enable-preview' +} + +tasks.withType(Test).configureEach { + jvmArgs += '--enable-preview' +} + +test { + useJUnitPlatform() +} + +tasks.withType(JavaExec).configureEach { + jvmArgs += [ + '-Dfile.encoding=UTF-8', + '-Dsun.stdout.encoding=UTF-8', + '-Dsun.stderr.encoding=UTF-8', + '--enable-preview' + ] + + // Для Windows консоли + systemProperty 'file.encoding', 'UTF-8' +} \ No newline at end of file diff --git a/build.gradle.kts b/build.gradle.kts deleted file mode 100644 index 79bf52a..0000000 --- a/build.gradle.kts +++ /dev/null @@ -1,20 +0,0 @@ -plugins { - id("java") -} - -group = "org.lab" -version = "1.0-SNAPSHOT" - -repositories { - mavenCentral() -} - -dependencies { - testImplementation(platform("org.junit:junit-bom:5.10.0")) - testImplementation("org.junit.jupiter:junit-jupiter") - testRuntimeOnly("org.junit.platform:junit-platform-launcher") -} - -tasks.test { - useJUnitPlatform() -} \ No newline at end of file diff --git a/settings.gradle.kts b/settings.gradle similarity index 100% rename from settings.gradle.kts rename to settings.gradle diff --git a/src/main/java/org/lab/Main.java b/src/main/java/org/lab/Main.java index 22028ef..e4dafb9 100644 --- a/src/main/java/org/lab/Main.java +++ b/src/main/java/org/lab/Main.java @@ -1,4 +1,117 @@ + + +import org.lab.model.milestone.MilestoneStatus; +import org.lab.model.project.Project; +import org.lab.model.report.Report; +import org.lab.model.ticket.Ticket; +import org.lab.model.user.User; +import org.lab.service.UserService; + + + +import java.time.LocalDate; + void main() { - IO.println("Hello and welcome!"); + + UserService userService = new UserService(); + User manager = userService.registerUser("Manager"); + + + + Project project1 = new Project(manager, "Valhalla"); + + + User developer1 = userService.registerUser("Developer1"); + User developer2 = userService.registerUser("Developer2"); + User developer3 = userService.registerUser("Developer3"); + + User qa1 = userService.registerUser("QA1"); + User qa2 = userService.registerUser("QA2"); + User qa3 = userService.registerUser("QA3"); + + User teamLead = userService.registerUser("TeamLead"); + + + + project1.attachTeamLead(manager, teamLead); + + project1.attachDeveloper(manager, developer1); + project1.attachDeveloper(manager, developer2); + project1.attachDeveloper(manager, developer3); + + project1.attachQa(manager, qa1); + project1.attachQa(manager, qa2); + project1.attachQa(manager, qa3); + + + project1.attachMilestone(manager, LocalDate.now(), LocalDate.now().plusDays(15)); + project1.changeMilestoneStatus(manager, MilestoneStatus.ACTIVE); + + Ticket ticket1 = project1.addTicket(manager, "Ticket1"); + Ticket ticket2 = project1.addTicket(manager, "Ticket2"); + Ticket ticket3 = project1.addTicket(teamLead, "Ticket3"); + + System.out.println(project1.getStats()); + + + ticket1.addDeveloper(manager, developer1); + ticket2.addDeveloper(manager, developer2); + ticket3.addDeveloper(teamLead, developer3); + + ticket1.activeTicket(developer1); + ticket2.activeTicket(developer2); + ticket3.activeTicket(developer3); + + ticket1.finishTicket(developer1); + ticket2.finishTicket(developer2); + ticket3.finishTicket(developer3); + + + + Report report1 = project1.addReport(qa1, developer1, "bug-report1"); + Report report2 = project1.addReport(qa2, developer2, "bug-report2"); + Report report3 = project1.addReport(qa3, developer3, "bug-report3"); + + report1.fixedReport(developer1); + report2.fixedReport(developer2); + report3.fixedReport(developer3); + + report1.checkReport(qa1); + report2.checkReport(qa2); + report3.checkReport(qa3); + + report1.closeReport(qa1); + report2.closeReport(qa2); + report3.closeReport(qa3); + + + + manager.viewAllProjects(); + teamLead.viewAllProjects(); + developer1.viewAllProjects(); + developer2.viewAllProjects(); + developer3.viewAllProjects(); + qa1.viewAllProjects(); + qa2.viewAllProjects(); + qa3.viewAllProjects(); + + manager.viewAllTasks(); + teamLead.viewAllTasks(); + developer1.viewAllTasks(); + developer2.viewAllTasks(); + developer3.viewAllTasks(); + qa1.viewAllTasks(); + qa2.viewAllTasks(); + qa3.viewAllTasks(); + + developer1.viewAllReport(); + developer2.viewAllReport(); + developer3.viewAllReport(); + + + + project1.changeMilestoneStatus(manager, MilestoneStatus.CLOSE); + System.out.println(project1.getMilestones()); + } diff --git a/src/main/java/org/lab/model/milestone/Milestone.java b/src/main/java/org/lab/model/milestone/Milestone.java new file mode 100644 index 0000000..667fefe --- /dev/null +++ b/src/main/java/org/lab/model/milestone/Milestone.java @@ -0,0 +1,57 @@ +package org.lab.model.milestone; + +import org.lab.model.ticket.Ticket; + +import java.time.LocalDate; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class Milestone { + + private String milestoneId; + + private String projectId; + + private LocalDate startDate; + + private LocalDate endDate; + + private MilestoneStatus status; + + private List tickets = new ArrayList<>(); + + public Milestone(String projectId, LocalDate startDate, LocalDate endDate) { + milestoneId = UUID.randomUUID().toString(); + this.projectId = projectId; + this.startDate = startDate; + this.endDate = endDate; + status = MilestoneStatus.OPEN; + } + + public MilestoneStatus getStatus() { + return status; + } + + public void setStatus(MilestoneStatus status) { + this.status = status; + } + + public String getMilestoneId() { + return milestoneId; + } + + public List getTickets() { + return tickets; + } + + @Override + public String toString() { + return "Milestone{" + + "startDate=" + startDate + + ", milestoneId='" + milestoneId + '\'' + + ", endDate=" + endDate + + ", status=" + status + + '}'; + } +} diff --git a/src/main/java/org/lab/model/milestone/MilestoneStatus.java b/src/main/java/org/lab/model/milestone/MilestoneStatus.java new file mode 100644 index 0000000..cb1cc72 --- /dev/null +++ b/src/main/java/org/lab/model/milestone/MilestoneStatus.java @@ -0,0 +1,7 @@ +package org.lab.model.milestone; + +public enum MilestoneStatus { + + OPEN, ACTIVE, CLOSE + +} diff --git a/src/main/java/org/lab/model/project/Project.java b/src/main/java/org/lab/model/project/Project.java new file mode 100644 index 0000000..35f444e --- /dev/null +++ b/src/main/java/org/lab/model/project/Project.java @@ -0,0 +1,284 @@ +package org.lab.model.project; + +import org.lab.model.milestone.Milestone; +import org.lab.model.milestone.MilestoneStatus; +import org.lab.model.report.Report; +import org.lab.model.role.Developer; +import org.lab.model.role.Manager; +import org.lab.model.role.QA; +import org.lab.model.role.TeamLead; +import org.lab.model.ticket.Ticket; +import org.lab.model.ticket.TicketStatus; +import org.lab.model.user.User; + +import java.time.LocalDate; +import java.util.*; + +public class Project { + + private String projectId; + + private User manager; + + private User teamLead; + + private Set developers = new HashSet<>(); + + private String description; + + private Set qa = new HashSet<>(); + + private LinkedList milestones = new LinkedList<>(); + + private List reports = new ArrayList<>(); + + + private Milestone currentMilestone; + + /** + * Создание проекта пользователем. + * + * @param user пользователь, от имени которого создаётся проект (он будет менеджером) + */ + public Project(User user, String description) { + + projectId = UUID.randomUUID().toString(); + manager = user; + this.description = description; + user.addProject(this, new Manager()); + + } + + /** + * Добавление тимлида к проекту. + */ + public void attachTeamLead(User manager, User teamLead) { + + if (!manager.equals(this.manager)) { + + String errorMessage = StringTemplate.STR.""" + User with name: \{manager.getFullName()} + and id: \{manager.getId()} + is not a manager of project with id: \{projectId}. + Insufficient permissions to perform this action. + """; + System.out.println(errorMessage); + return; + } + + this.teamLead = teamLead; + teamLead.addProject(this, new TeamLead()); + + } + + /** + * Добавление разработчика к проекту. + */ + public void attachDeveloper(User manager, User developer) { + + if (!manager.equals(this.manager)) { + String errorMessage = StringTemplate.STR.""" + User with name: \{manager.getFullName()} + and id: \{manager.getId()} + is not a manager of project with id: \{projectId}. + Insufficient permissions to perform this action. + """; + System.out.println(errorMessage); + return; + } + + this.developers.add(developer); + developer.addProject(this, new Developer()); + + } + + /** + * Добавление тестировщика к проекту. + */ + public void attachQa(User manager, User qa) { + + if (!manager.equals(this.manager)) { + String errorMessage = StringTemplate.STR.""" + User with name: \{manager.getFullName()} + and id: \{manager.getId()} + is not a manager of project with id: \{projectId}. + Insufficient permissions to perform this action. + """; + System.out.println(errorMessage); + return; + } + + this.qa.add(qa); + qa.addProject(this, new QA()); + + } + + /** + * Создать новый Milestone. + * + * @param start начало milestone. + * @param finish окончание milestone. + */ + public void attachMilestone(User manager, LocalDate start, LocalDate finish) { + + if (!manager.equals(this.manager)) { + String errorMessage = StringTemplate.STR.""" + User with name: \{manager.getFullName()} + and id: \{manager.getId()} + is not a manager of project with id: \{projectId}. + Insufficient permissions to perform this action. + """; + System.out.println(errorMessage); + return; + } + + if (Objects.nonNull(currentMilestone)) { + System.out.println("The current milestone has not yet ended, so you cannot create a new one."); + return; + } + + Milestone milestone = new Milestone(projectId, start, finish); + currentMilestone = milestone; + milestones.push(milestone); + + } + + /** + * Изменить статус текущего milestone + */ + public void changeMilestoneStatus(User manager, MilestoneStatus newStatus) { + + if (!manager.equals(this.manager)) { + String errorMessage = StringTemplate.STR.""" + User with name: \{manager.getFullName()} + and id: \{manager.getId()} + is not a manager of project with id: \{projectId}. + Insufficient permissions to perform this action. + """; + System.out.println(errorMessage); + return; + } + + if (Objects.isNull(currentMilestone)) { + System.out.println("First, create the current milestone"); + return; + } + + + if (newStatus == MilestoneStatus.CLOSE) { + + for (Ticket ticket : currentMilestone.getTickets()) { + + if (ticket.getStatus() != TicketStatus.COMPLETED) { + + System.out.println("You cannot close the milestone because not all tickets have been completed."); + return; + } + + } + + currentMilestone.setStatus(newStatus); + currentMilestone = null; + return; + + } + + + currentMilestone.setStatus(newStatus); + + } + + /** + * Создание нового тикета (прикрепляется к текущему milestone) + */ + public Ticket addTicket(User user, String description) { + + if (!user.equals(this.manager) && !(Objects.nonNull(teamLead) && teamLead.equals(user))) { + String errorMessage = StringTemplate.STR.""" + User with name: \{manager.getFullName()} + and id: \{manager.getId()} + is not a manager of project with id: \{projectId}. + Insufficient permissions to perform this action. + """; + System.out.println(errorMessage); + return null; + } + + if (Objects.isNull(currentMilestone)) { + System.out.println("First, create the current milestone"); + return null; + } + + Ticket ticket = new Ticket(this, currentMilestone, description, user); + + currentMilestone.getTickets().add(ticket); + + return ticket; + + } + + /** + * Здесь разработчик или тестировщик может создать bug-report + */ + public Report addReport(User createdUser, User fixedUser, String description) { + + Report report = new Report(description, createdUser, fixedUser, this); + reports.add(report); + + return report; + + } + + public ProjectStatus getStats() { + + int totalTickets = milestones.stream() + .mapToInt(m -> m.getTickets().size()) + .sum(); + + int completedTickets = milestones.stream() + .flatMap(m -> m.getTickets().stream()) + .filter(t -> t.getStatus() == TicketStatus.COMPLETED) + .toList() + .size(); + + return new ProjectStatus( + description, + totalTickets, + completedTickets, + totalTickets - completedTickets, + developers.size(), + qa.size() + ); + } + + + public Set getDevelopers() { + return developers; + } + + public String getDescription() { + return description; + } + + public LinkedList getMilestones() { + return milestones; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Project project = (Project) o; + return Objects.equals(projectId, project.projectId); + } + + @Override + public int hashCode() { + return Objects.hashCode(projectId); + } + + public List getReports() { + return reports; + } + +} diff --git a/src/main/java/org/lab/model/project/ProjectStatus.java b/src/main/java/org/lab/model/project/ProjectStatus.java new file mode 100644 index 0000000..80084c2 --- /dev/null +++ b/src/main/java/org/lab/model/project/ProjectStatus.java @@ -0,0 +1,34 @@ +package org.lab.model.project; + +public record ProjectStatus( + String projectName, + int totalTickets, + int completedTickets, + int openTickets, + int totalDevelopers, + int totalQA +) { + + public double completionPercentage() { + return totalTickets > 0 ? (completedTickets * 100.0) / totalTickets : 0.0; + } + + @Override + public String toString() { + return STR.""" + + PROJECT STATUS REPORT + Project: \{projectName} + + TICKETS STATISTICS: + Total tickets: \{totalTickets} + Completed: \{completedTickets} + Open: \{openTickets} + Completion rate: \{String.format("%.1f", completionPercentage())}% + TEAM COMPOSITION: + Developers: \{totalDevelopers} + QA Engineers: \{totalQA} + """; + } + +} \ No newline at end of file diff --git a/src/main/java/org/lab/model/report/Report.java b/src/main/java/org/lab/model/report/Report.java new file mode 100644 index 0000000..5274ea5 --- /dev/null +++ b/src/main/java/org/lab/model/report/Report.java @@ -0,0 +1,137 @@ +package org.lab.model.report; + +import org.lab.model.project.Project; +import org.lab.model.user.User; + +import java.util.Objects; +import java.util.UUID; + +public class Report { + + private String reportId; + + private String description; + + /** + * Пользователь, кто создал сообщение об ошибки + */ + private User createdUser; + + /** + * Пользователь, кто исправил сообщение об ошибки + */ + private User fixedUser; + + private Project project; + + private ReportStatus status; + + public Report(String description, User createdUser, User fixedUser, Project project) { + reportId = UUID.randomUUID().toString(); + this.description = description; + this.createdUser = createdUser; + this.project = project; + this.fixedUser = fixedUser; + status = ReportStatus.NEW; + } + + + /** + * Разработчик устраняет сообщение об ошибке. + */ + public void fixedReport(User developer) { + + if (!project.getDevelopers().contains(developer)) { + + String errorMessage = "Insufficient permissions to perform this action."; + System.out.println(errorMessage); + return; + + } + + if (!fixedUser.equals(developer)) { + + String errorMessage = "Insufficient permissions to perform this action."; + System.out.println(errorMessage); + return; + + } + + status = ReportStatus.FIXED; + + } + + /** + * Тестировщик проверяет как исправил bug-report разработчик. + */ + public void checkReport(User user) { + + if (!user.equals(createdUser)) { + + String errorMessage = "Insufficient permissions to perform this action."; + System.out.println(errorMessage); + return; + } + + status = ReportStatus.TESTED; + + } + + /** + * Тестировщик закрывает bug-report + */ + public void closeReport(User user) { + + if (!user.equals(createdUser)) { + + String errorMessage = "Insufficient permissions to perform this action."; + System.out.println(errorMessage); + return; + } + + status = ReportStatus.CLOSED; + + } + + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Report report = (Report) o; + return Objects.equals(reportId, report.reportId); + } + + @Override + public int hashCode() { + return Objects.hashCode(reportId); + } + + public User getCreatedUser() { + return createdUser; + } + + public String getDescription() { + return description; + } + + public User getFixedUser() { + return fixedUser; + } + + @Override + public String toString() { + return STR.""" + Report [ + ID: \{reportId} + Description: \{description} + Status: \{status} + Created by: \{createdUser.getFullName()} + Assigned to: \{fixedUser.getFullName()} + Project: \{project.getDescription()} + ] + """; + } + + +} diff --git a/src/main/java/org/lab/model/report/ReportStatus.java b/src/main/java/org/lab/model/report/ReportStatus.java new file mode 100644 index 0000000..1eaafd9 --- /dev/null +++ b/src/main/java/org/lab/model/report/ReportStatus.java @@ -0,0 +1,8 @@ +package org.lab.model.report; + +public enum ReportStatus { + + NEW, FIXED, TESTED, CLOSED + + +} diff --git a/src/main/java/org/lab/model/role/Developer.java b/src/main/java/org/lab/model/role/Developer.java new file mode 100644 index 0000000..4baadc7 --- /dev/null +++ b/src/main/java/org/lab/model/role/Developer.java @@ -0,0 +1,10 @@ +package org.lab.model.role; + +public final class Developer implements Role { + + @Override + public String getRoleName() { + return "Developer"; + } + +} diff --git a/src/main/java/org/lab/model/role/Manager.java b/src/main/java/org/lab/model/role/Manager.java new file mode 100644 index 0000000..f028c5a --- /dev/null +++ b/src/main/java/org/lab/model/role/Manager.java @@ -0,0 +1,10 @@ +package org.lab.model.role; + +public final class Manager implements Role { + + @Override + public String getRoleName() { + return "Manager"; + } + +} diff --git a/src/main/java/org/lab/model/role/QA.java b/src/main/java/org/lab/model/role/QA.java new file mode 100644 index 0000000..5a74f06 --- /dev/null +++ b/src/main/java/org/lab/model/role/QA.java @@ -0,0 +1,10 @@ +package org.lab.model.role; + +public final class QA implements Role { + + @Override + public String getRoleName() { + return "QA"; + } + +} diff --git a/src/main/java/org/lab/model/role/Role.java b/src/main/java/org/lab/model/role/Role.java new file mode 100644 index 0000000..47d6c30 --- /dev/null +++ b/src/main/java/org/lab/model/role/Role.java @@ -0,0 +1,13 @@ +package org.lab.model.role; + + + +/** + * Роли участников проекта. + */ +public sealed interface Role permits Manager, Developer, TeamLead, QA { + + String getRoleName(); + +} + diff --git a/src/main/java/org/lab/model/role/TeamLead.java b/src/main/java/org/lab/model/role/TeamLead.java new file mode 100644 index 0000000..18a728f --- /dev/null +++ b/src/main/java/org/lab/model/role/TeamLead.java @@ -0,0 +1,10 @@ +package org.lab.model.role; + +public final class TeamLead implements Role { + + @Override + public String getRoleName() { + return "TeamLead"; + } + +} diff --git a/src/main/java/org/lab/model/ticket/Ticket.java b/src/main/java/org/lab/model/ticket/Ticket.java new file mode 100644 index 0000000..34ced7f --- /dev/null +++ b/src/main/java/org/lab/model/ticket/Ticket.java @@ -0,0 +1,144 @@ +package org.lab.model.ticket; + +import org.lab.model.milestone.Milestone; +import org.lab.model.project.Project; +import org.lab.model.user.User; + +import java.util.*; + +public class Ticket { + + private String ticketId; + + private Project project; + + private Milestone milestone; + + private String description; + + private Set developers = new HashSet<>(); + + private int count = 0; + + private TicketStatus status; + + /** + * TeamLead или менеджер проекта, кто создал тикет. + */ + private User createdUser; + + public Ticket(Project project, Milestone milestone, String description, User createdUser) { + ticketId = UUID.randomUUID().toString(); + this.project = project; + this.milestone = milestone; + this.description = description; + this.createdUser = createdUser; + status = TicketStatus.NEW; + } + + /** + * Посмотреть статус тикета + */ + public TicketStatus getStatus() { + return status; + } + + public String getDescription() { + return description; + } + + /** + * Привязка разработчика к тикету. + */ + public void addDeveloper(User createdUser, User developer) { + + if (!createdUser.equals(this.createdUser)) { + + String errorMessage = "Insufficient permissions to perform this action."; + System.out.println(errorMessage); + return; + + } + + + if (!project.getDevelopers().contains(developer)) { + + String errorMessage = "The developer is not part of the project they are attached to this ticket."; + System.out.println(errorMessage); + return; + } + + + developers.add(developer); + status = TicketStatus.ACCEPTED; + count++; + } + + /** + * Разработчик выполняет задачу в тикете. + */ + public void activeTicket(User developer) { + + if (!developers.contains(developer)) { + String errorMessage = "Insufficient permissions to perform this action."; + System.out.println(errorMessage); + return; + } + + if (status == TicketStatus.COMPLETED) { + + String errorMessage = "The task in the ticket has already been completed."; + System.out.println(errorMessage); + return; + + } + + + status = TicketStatus.ACTIVE; + + + } + + /** + * Разработчик выполнил задачу в тикете. + */ + public void finishTicket(User developer) { + + if (!developers.contains(developer)) { + String errorMessage = "Insufficient permissions to perform this action."; + System.out.println(errorMessage); + return; + } + + count--; + if (count == 0) { + status = TicketStatus.COMPLETED; + } + + } + + public String getStatusDescription() { + return switch(status) { + case NEW -> "New task"; + case ACCEPTED -> "Accepted for work"; + case ACTIVE -> "In progress"; + case COMPLETED -> "Completed"; + }; + } + + public Set getDevelopers() { + return developers; + } + + @Override + public String toString() { + return StringTemplate.STR.""" + Ticket: \{description} + Status: \{getStatusDescription()} + Developers: \{developers.size()} + Created by: \{createdUser.getFullName()} + """; + } + + +} diff --git a/src/main/java/org/lab/model/ticket/TicketStatus.java b/src/main/java/org/lab/model/ticket/TicketStatus.java new file mode 100644 index 0000000..fdafac1 --- /dev/null +++ b/src/main/java/org/lab/model/ticket/TicketStatus.java @@ -0,0 +1,7 @@ +package org.lab.model.ticket; + +public enum TicketStatus { + + NEW, ACCEPTED, ACTIVE, COMPLETED + +} diff --git a/src/main/java/org/lab/model/user/User.java b/src/main/java/org/lab/model/user/User.java new file mode 100644 index 0000000..84ed437 --- /dev/null +++ b/src/main/java/org/lab/model/user/User.java @@ -0,0 +1,144 @@ +package org.lab.model.user; + +import org.lab.model.project.Project; +import org.lab.model.role.Role; + +import java.util.*; +import java.util.stream.Collectors; + + +public class User { + + /** + * Уникальные идентификатор пользователя в системе. + */ + private String id; + + /** + * Полное имя пользователя. + */ + private String fullName; + + /** + * + * Список ролей в разных проектах. (допускается в одном проекте иметь несколько ролей) + */ + private Map> roles = new HashMap<>(); + + + public User(String fullName) { + this.fullName = fullName; + } + + + /** + * Назначить роль в проекте. + */ + public void addProject(Project project, Role role) { + + Set currentRoles = roles.computeIfAbsent(project, k -> new HashSet<>()); + currentRoles.add(role); + + } + + /** + * Просмотреть все проекты + */ + public void viewAllProjects() { + + roles.forEach((project, roleSet) -> { + String rolesStr = roleSet.stream() + .map(Role::getRoleName) + .collect(Collectors.joining(", ")); + + System.out.println(STR.""" + Project: \{project.getDescription()} + Roles: \{rolesStr} + """); + }); + + } + + /** + * Просмотреть все задачи + */ + public void viewAllTasks() { + + System.out.println("User: " + fullName); + + roles.forEach((project, _) -> { + System.out.println("Project: " + project.getDescription()); + + + project.getMilestones().forEach(milestone -> { + System.out.println("Milestone " + milestone.getMilestoneId()); + System.out.println("Tasks:"); + + milestone.getTickets().stream() + .filter(ticket -> ticket.getDevelopers().contains(this)) + .forEach(System.out::println); + + System.out.println("--------------"); + }); + + + System.out.println("Reports"); + project.getReports().stream() + .filter(report -> report.getCreatedUser().equals(this)) + .forEach(System.out::println); + + System.out.println("--------------"); + }); + + + } + + public void viewAllReport() { + + System.out.println("User: " + fullName); + + roles.forEach((project, _) -> { + System.out.println("Project: " + project.getDescription()); + + System.out.println("Reports"); + project.getReports().stream() + .filter(report -> report.getFixedUser().equals(this)) + .map(report -> "Description: " + report.getDescription()) + .forEach(System.out::println); + + System.out.println("--------------"); + }); + + } + + public String getId() { + return id; + } + + public void setId(String id) { + this.id = id; + } + + public String getFullName() { + return fullName; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return Objects.equals(id, user.id); + } + + @Override + public int hashCode() { + return Objects.hashCode(id); + } + +} + + + + + diff --git a/src/main/java/org/lab/service/UserService.java b/src/main/java/org/lab/service/UserService.java new file mode 100644 index 0000000..39ef954 --- /dev/null +++ b/src/main/java/org/lab/service/UserService.java @@ -0,0 +1,30 @@ +package org.lab.service; + +import org.lab.model.user.User; + +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; + +public class UserService { + + private Map users; + + public UserService() { + users = new HashMap<>(); + } + + public User registerUser(String fullName) { + + String id = UUID.randomUUID().toString(); + User user = new User(fullName); + user.setId(id); + + users.put(id, user); + + return user; + + } + + +}