feat(reporting): compose role dashboards from feature services
This commit is contained in:
+40
@@ -0,0 +1,40 @@
|
||||
package com.lab.labtimesheet.feature.reporting.controller;
|
||||
|
||||
import com.lab.labtimesheet.feature.reporting.exception.DashboardAccessDeniedException;
|
||||
import com.lab.labtimesheet.feature.reporting.service.DashboardService;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.ui.Model;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
|
||||
@Controller
|
||||
public class DashboardController {
|
||||
|
||||
private final DashboardService dashboardService;
|
||||
|
||||
public DashboardController(DashboardService dashboardService) {
|
||||
this.dashboardService = dashboardService;
|
||||
}
|
||||
|
||||
@GetMapping("/dashboard")
|
||||
public String dashboard(Authentication authentication, Model model) {
|
||||
String email = authentication.getName();
|
||||
if (hasRole(authentication, "ROLE_ADMIN")) {
|
||||
model.addAttribute("dashboard", dashboardService.admin(email));
|
||||
return "dashboard/admin";
|
||||
}
|
||||
if (hasRole(authentication, "ROLE_MENTOR")) {
|
||||
model.addAttribute("dashboard", dashboardService.mentor(email));
|
||||
return "dashboard/mentor";
|
||||
}
|
||||
if (hasRole(authentication, "ROLE_INTERN")) {
|
||||
model.addAttribute("dashboard", dashboardService.intern(email));
|
||||
return "dashboard/intern";
|
||||
}
|
||||
throw new DashboardAccessDeniedException("Dashboard access requires a supported global role");
|
||||
}
|
||||
|
||||
private boolean hasRole(Authentication authentication, String role) {
|
||||
return authentication.getAuthorities().stream().anyMatch(authority -> authority.getAuthority().equals(role));
|
||||
}
|
||||
}
|
||||
+13
@@ -0,0 +1,13 @@
|
||||
package com.lab.labtimesheet.feature.reporting.exception;
|
||||
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.web.bind.annotation.ResponseStatus;
|
||||
|
||||
@ResponseStatus(HttpStatus.FORBIDDEN)
|
||||
public class DashboardAccessDeniedException extends AccessDeniedException {
|
||||
|
||||
public DashboardAccessDeniedException(String message) {
|
||||
super(message);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,97 @@
|
||||
package com.lab.labtimesheet.feature.reporting.service;
|
||||
|
||||
import com.lab.labtimesheet.feature.account.model.AccountStatus;
|
||||
import com.lab.labtimesheet.feature.account.model.GlobalRole;
|
||||
import com.lab.labtimesheet.feature.account.model.dto.AccountIdentity;
|
||||
import com.lab.labtimesheet.feature.account.model.dto.AccountSummary;
|
||||
import com.lab.labtimesheet.feature.account.service.AccountService;
|
||||
import com.lab.labtimesheet.feature.attendance.exception.AttendanceException;
|
||||
import com.lab.labtimesheet.feature.attendance.model.dto.AttendanceCurrentState;
|
||||
import com.lab.labtimesheet.feature.attendance.service.AttendanceApplicationService;
|
||||
import com.lab.labtimesheet.feature.reporting.exception.DashboardAccessDeniedException;
|
||||
import com.lab.labtimesheet.feature.reporting.model.dto.DashboardView;
|
||||
import com.lab.labtimesheet.feature.reporting.model.dto.DashboardView.AssignedTask;
|
||||
import com.lab.labtimesheet.feature.reporting.model.dto.DashboardView.AttendanceState;
|
||||
import com.lab.labtimesheet.feature.project.model.dto.ProjectDashboardSummary;
|
||||
import com.lab.labtimesheet.feature.project.service.ProjectQueryService;
|
||||
import com.lab.labtimesheet.feature.task.model.dto.TaskDashboardView;
|
||||
import com.lab.labtimesheet.feature.task.service.TaskDashboardService;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
@Service
|
||||
@Transactional(readOnly = true)
|
||||
public class DashboardService {
|
||||
|
||||
private final AccountService accounts;
|
||||
private final ProjectQueryService projects;
|
||||
private final TaskDashboardService tasks;
|
||||
private final AttendanceApplicationService attendance;
|
||||
|
||||
public DashboardService(
|
||||
AccountService accounts,
|
||||
ProjectQueryService projects,
|
||||
TaskDashboardService tasks,
|
||||
AttendanceApplicationService attendance) {
|
||||
this.accounts = accounts;
|
||||
this.projects = projects;
|
||||
this.tasks = tasks;
|
||||
this.attendance = attendance;
|
||||
}
|
||||
|
||||
public DashboardView.Admin admin(String email) {
|
||||
AccountIdentity admin = activeAccount(email, GlobalRole.ADMIN);
|
||||
AccountSummary accountSummary = accounts.summary();
|
||||
ProjectDashboardSummary projectSummary = projects.dashboardSummary(admin.id());
|
||||
return new DashboardView.Admin(
|
||||
accountSummary.activeAccounts(),
|
||||
accountSummary.pendingActivations(),
|
||||
accountSummary.activeInternships(),
|
||||
projectSummary.activeProjectCount());
|
||||
}
|
||||
|
||||
public DashboardView.Mentor mentor(String email) {
|
||||
AccountIdentity mentor = activeAccount(email, GlobalRole.MENTOR);
|
||||
ProjectDashboardSummary projectSummary = projects.dashboardSummary(mentor.id());
|
||||
TaskDashboardView taskSummary = tasks.dashboard(email);
|
||||
return new DashboardView.Mentor(
|
||||
mentor.displayName(),
|
||||
projectSummary.activeProjectCount(),
|
||||
projectSummary.distinctActiveMemberCount(),
|
||||
taskSummary.blockedTaskCount());
|
||||
}
|
||||
|
||||
public DashboardView.Intern intern(String email) {
|
||||
AccountIdentity intern = activeAccount(email, GlobalRole.INTERN);
|
||||
AttendanceCurrentState attendanceState;
|
||||
try {
|
||||
attendanceState = attendance.currentState(intern.id());
|
||||
} catch (AttendanceException exception) {
|
||||
throw new DashboardAccessDeniedException("Active Intern account and internship required");
|
||||
}
|
||||
ProjectDashboardSummary projectSummary = projects.dashboardSummary(intern.id());
|
||||
TaskDashboardView taskSummary = tasks.dashboard(email);
|
||||
return new DashboardView.Intern(
|
||||
intern.displayName(),
|
||||
AttendanceState.valueOf(attendanceState.name()),
|
||||
projectSummary.activeProjectCount(),
|
||||
taskSummary.assignedTaskCount(),
|
||||
taskSummary.priorityTasks().stream()
|
||||
.map(task -> new AssignedTask(
|
||||
task.title(), task.projectName(), task.status().name(), task.dueDate()))
|
||||
.toList());
|
||||
}
|
||||
|
||||
private AccountIdentity activeAccount(String email, GlobalRole role) {
|
||||
AccountIdentity account;
|
||||
try {
|
||||
account = accounts.requireIdentityByEmail(email);
|
||||
} catch (IllegalArgumentException exception) {
|
||||
throw new DashboardAccessDeniedException("Active " + role + " account required");
|
||||
}
|
||||
if (account.status() != AccountStatus.ACTIVE || account.role() != role) {
|
||||
throw new DashboardAccessDeniedException("Active " + role + " account required");
|
||||
}
|
||||
return account;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user