Feature: Dashboard
Relevant source files
The following files were used as context for generating this wiki page:- src/main/java/com/paymaster/backend/presentation/controller/HomeController.java
- src/main/java/com/paymaster/backend/domain/service/DashboardService.java
- src/main/resources/templates/reports/index.html
- src/main/resources/templates/installments/list.html
- src/main/resources/templates/contracts/list.html
- src/main/resources/templates/fragments/layout.html
- src/main/resources/static/js/app.js
The Dashboard is the central landing page of the PayMaster application. It serves as an information hub, providing users with a real-time, high-level overview of the system's financial health and operational status. The dashboard aggregates key metrics, highlights urgent items like overdue installments, and offers quick navigation to other critical sections of the application.
Backend Architecture
The dashboard's data is prepared on the backend by a controller and a dedicated service layer before being rendered by the frontend.
Data Flow
When a user navigates to the application's root (/) or the /dashboard path, the HomeController intercepts the request. It then calls the DashboardService to gather all necessary statistics and data lists. This data is added to the Spring Model and passed to the Thymeleaf view for rendering.
The following sequence diagram illustrates the data retrieval process for the dashboard.
Key Components
HomeController
The HomeController is responsible for handling requests for the dashboard page. The dashboard() method orchestrates the data collection and view rendering.
// src/main/java/com/paymaster/backend/presentation/controller/HomeController.java:40-54
@GetMapping({"/", "/dashboard"})
public String dashboard(Model model) {
DashboardService.DashboardStats stats = dashboardService.getDashboardStats();
List<Installment> upcomingInstallments = dashboardService.getUpcomingInstallments();
List<Installment> overdueInstallments = dashboardService.getOverdueInstallments();
List<Contract> overdueContracts = dashboardService.getOverdueContracts();
model.addAttribute("stats", stats);
model.addAttribute("upcomingInstallments", upcomingInstallments);
model.addAttribute("overdueInstallments", overdueInstallments);
model.addAttribute("overdueContracts", overdueContracts);
model.addAttribute("dateUtils", dateUtils);
return "dashboard";
}
Sources: src/main/java/com/paymaster/backend/presentation/controller/HomeController.java:40-54
DashboardService
This service acts as a facade to aggregate data from other services (CustomerService, ContractService, InstallmentService). It encapsulates the logic for calculating system-wide statistics.
The class diagram below shows the dependencies of DashboardService.
Data Model: DashboardStats
The DashboardService populates a DashboardStats object, which is a static inner class designed to hold all key metrics for the dashboard.
| Field | Type | Description |
|---|---|---|
totalCustomers | long | The total number of customers in the system. |
activeCustomers | long | The number of customers with an 'ACTIVE' status. |
totalContracts | long | The total number of contracts created. |
activeContracts | long | The number of contracts that are currently active. |
overdueInstallments | long | The count of installments that are past their due date. |
totalReceivable | long | The total amount of all active contracts. |
totalReceived | long | The sum of all paid amounts across all installments. |
totalOverdue | long | The sum of remaining amounts for overdue installments. |
totalPenalty | long | The sum of all collected penalty fees. |
todayPersianDate | String | The current date in Persian format. |
The class also includes helper methods like getCollectionPercentage() and getTotalReceivableFormatted() for presentation logic.
Sources: src/main/java/com/paymaster/backend/domain/service/DashboardService.java:78-91
Frontend Rendering
The frontend is rendered using Thymeleaf. While the specific dashboard.html file was not provided for analysis, its structure can be inferred from the data passed by HomeController and by examining similar view templates like reports/index.html.
The following diagram shows the likely layout of the dashboard page.
Statistics Cards
The dashboard prominently displays key performance indicators (KPIs) in "stats cards". These provide a quick, at-a-glance view of the system's status. The styling for these cards is defined in style.css under the .stats-card class.
Example rendering from a similar page (reports/index.html):
<!-- src/main/resources/templates/reports/index.html:19-27 -->
<div class="col-md-3">
<div class="card border-0 shadow-sm text-center py-4">
<div class="card-body">
<i class="bi bi-people fs-1 text-primary mb-3 d-block"></i>
<h3 th:text="${stats.totalCustomers}">0</h3>
<p class="text-muted mb-0">کل مشتریان</p>
</div>
</div>
</div>
Sources: src/main/resources/templates/reports/index.html:19-27, src/main/resources/static/css/style.css:243-259
Data Lists
The HomeController prepares three lists for display on the dashboard:
- Overdue Installments: A list of installments that are past their due date and not fully paid.
- Upcoming Installments: A list of installments due within the current week.
- Overdue Contracts: A list of contracts that have at least one overdue installment.
These are likely rendered in tables, similar to the views in installments/list.html and contracts/list.html, to provide actionable information to the user.
Sources: src/main/java/com/paymaster/backend/presentation/controller/HomeController.java:43-45, src/main/resources/templates/installments/list.html, src/main/resources/templates/contracts/list.html
Navigation
The main navigation bar, defined in fragments/layout.html, includes a direct link to the Dashboard, making it the primary entry point for users. The link is marked as active when the user is on the / or /dashboard URI.
<!-- src/main/resources/templates/fragments/layout.html:28-32 -->
<li class="nav-item">
<a class="nav-link" th:href="@{/dashboard}"
th:classappend="${#httpServletRequest.requestURI == '/dashboard' || #httpServletRequest.requestURI == '/'} ? 'active'">
<i class="bi bi-speedometer2 me-1"></i> داشبورد
</a>
</li>
Sources: src/main/resources/templates/fragments/layout.html:28-32