完成报表中心

This commit is contained in:
Zzzz
2026-04-27 22:07:20 +08:00
parent d503036aeb
commit f9a9c630c2
26 changed files with 1127 additions and 4 deletions
+89 -3
View File
@@ -29,9 +29,6 @@ Implemented scaffold tables:
status.
- `readers`: reader profiles, optional login-account linkage, borrowing
eligibility, contact information, and management status.
Planned module tables:
- `borrow_records`: book-reader borrowing, return, renew, and overdue data.
Record new schema changes in `src/main/resources/db/schema.sql` and update this
@@ -427,6 +424,95 @@ borrowing/manage.jsp -> JDBC -> UPDATE books SET available_copies = ...
borrowing/form.jsp -> BorrowingManagementServlet -> BorrowingService -> BorrowRecordDao -> borrow_records + books in one transaction
```
## Scenario: Report Center Slice
### 1. Scope / Trigger
- Trigger: the report center adds staff-only operational reporting across
`books`, `readers`, and `borrow_records` without adding report tables.
- Schema path: `src/main/resources/db/schema.sql`.
- JSP path: `WEB-INF/jsp/reports/dashboard.jsp`.
### 2. Signatures
- Entity signatures:
- `InventorySummary(totalTitles, totalCopies, availableCopies,
unavailableOrEmptyTitles)`.
- `BorrowingSummary(activeLoans, returnedLoans, overdueLoans)`.
- `OverdueReportRow(readerIdentifier, readerName, bookIdentifier,
bookTitle, dueAt, overdueDays)`.
- `PopularBookReportRow(bookIdentifier, title, author, borrowCount)`.
- `ReportCenter(inventorySummary, borrowingSummary, overdueRows,
popularBooks)`.
- DAO signatures: `ReportDao.loadInventorySummary()`,
`loadBorrowingSummary()`, `findOverdueRows()`, and
`findPopularBooks(int limit)`.
- Service signature: `ReportService.loadReportCenter(AuthenticatedUser actor)`
returning `ServiceResult<ReportCenter>`.
- Servlet route: `GET /reports`.
- Protected permission: `/reports` requires `VIEW_REPORTS`.
### 3. Contracts
- Report data is read-only and derived from existing `books`, `readers`, and
`borrow_records` rows; do not introduce aggregate/cache tables for the MVP.
- `unavailableOrEmptyTitles` counts book rows where `books.status` is not
`available` or `books.available_copies <= 0`.
- `activeLoans` counts active borrow rows where `returned_at IS NULL`.
- `returnedLoans` counts rows with `status = returned`.
- `overdueLoans` and overdue rows use the derived rule
`status = active AND returned_at IS NULL AND due_at < CURRENT_TIMESTAMP`.
- Popular book ranking groups by book and orders by borrow record count
descending, with a service/DAO limit for the top rows.
- `ReportServlet` sets the `reportCenter` request attribute on success and
`errorMessage` on safe service failure.
- JSP pages render JavaBean properties only; they must not call DAOs or embed
SQL.
- Dashboard, role-home, and header navigation should expose reports only to
administrator/librarian users.
### 4. Validation & Error Matrix
- Missing or unauthenticated actor -> `You do not have permission to view reports.`
- Reader actor -> `You do not have permission to view reports.`
- DAO failure while loading any report section -> log server-side details and
return `Report service is temporarily unavailable. Please try again later.`
- Empty overdue list -> render a stable empty state, not an error.
- Empty popular ranking -> render a stable empty state, not an error.
### 5. Good/Base/Bad Cases
- Good: a librarian opens `/reports` and sees inventory totals, borrowing
counts, active overdue rows, and top borrowed books.
- Base: no borrowing records exist; summaries show zero counts and tables show
empty states.
- Bad: a reader reaches `/reports`, a JSP performs `SELECT` queries directly,
or report queries update inventory/borrow state.
### 6. Tests Required
- Run `ReportServiceCheck` assertions for reader denial, librarian success,
report section composition, and DAO failure fallback.
- Run `PermissionPolicyCheck` to confirm administrator/librarian roles allow
`VIEW_REPORTS` and readers do not.
- Scan report JSPs for scriptlets and SQL/JDBC references.
- When Maven/Tomcat dependencies are installed, run `mvn clean package` to
compile Servlets and package JSP resources.
### 7. Wrong vs Correct
#### Wrong
```text
reports/dashboard.jsp -> JDBC -> SELECT COUNT(*) FROM borrow_records
```
#### Correct
```text
reports/dashboard.jsp <- ReportServlet <- ReportService <- ReportDao <- books/readers/borrow_records
```
## Scenario: Login And Permission Scaffold Schema
### 1. Scope / Trigger