完成报表中心
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{"file": ".trellis/spec/backend/index.md", "reason": "Backend architecture and checklist for reviewing Servlet-Service-DAO report changes."}
|
||||
{"file": ".trellis/spec/backend/directory-structure.md", "reason": "Verify report classes are placed consistently with backend structure."}
|
||||
{"file": ".trellis/spec/backend/database-guidelines.md", "reason": "Review JDBC aggregate queries and DAO boundaries for report data."}
|
||||
{"file": ".trellis/spec/backend/error-handling.md", "reason": "Verify servlet/service validation and failure behavior."}
|
||||
{"file": ".trellis/spec/backend/quality-guidelines.md", "reason": "Check maintainability, focused tests, and layer boundaries."}
|
||||
{"file": ".trellis/spec/frontend/index.md", "reason": "Review JSP report page against frontend conventions."}
|
||||
{"file": ".trellis/spec/frontend/directory-structure.md", "reason": "Verify JSP placement and shared layout usage."}
|
||||
{"file": ".trellis/spec/frontend/component-guidelines.md", "reason": "Check dashboard cards, tables, and report UI consistency."}
|
||||
{"file": ".trellis/spec/frontend/state-management.md", "reason": "Verify servlet-to-JSP request state is explicit and null-safe."}
|
||||
{"file": ".trellis/spec/frontend/quality-guidelines.md", "reason": "Check UI consistency and responsive/server-rendered page quality."}
|
||||
{"file": ".trellis/spec/guides/cross-layer-thinking-guide.md", "reason": "Reports span DAO, service, servlet, JSP, and permissions."}
|
||||
{"file": ".trellis/tasks/archive/2026-04/00-bootstrap-guidelines/research/project-requirements.md", "reason": "Original project requirements include reports and statistics expectations."}
|
||||
@@ -0,0 +1,14 @@
|
||||
{"file": ".trellis/spec/backend/index.md", "reason": "Backend architecture and pre-development checklist for Servlet-Service-DAO work."}
|
||||
{"file": ".trellis/spec/backend/directory-structure.md", "reason": "Place report controller, service, DAO, and entities consistently."}
|
||||
{"file": ".trellis/spec/backend/database-guidelines.md", "reason": "Use MySQL/JDBC aggregate queries and DAO boundaries correctly."}
|
||||
{"file": ".trellis/spec/backend/error-handling.md", "reason": "Follow existing servlet/service validation and safe failure patterns."}
|
||||
{"file": ".trellis/spec/backend/logging-guidelines.md", "reason": "Consider reporting and maintenance logging conventions without over-scoping."}
|
||||
{"file": ".trellis/spec/backend/quality-guidelines.md", "reason": "Maintain layer boundaries and focused verification."}
|
||||
{"file": ".trellis/spec/frontend/index.md", "reason": "JSP/CSS presentation conventions for server-rendered report pages."}
|
||||
{"file": ".trellis/spec/frontend/directory-structure.md", "reason": "Place report JSPs and shared includes consistently."}
|
||||
{"file": ".trellis/spec/frontend/component-guidelines.md", "reason": "Reuse page, card, form, and table UI patterns."}
|
||||
{"file": ".trellis/spec/frontend/state-management.md", "reason": "Use request/session state correctly for server-rendered reports."}
|
||||
{"file": ".trellis/spec/frontend/type-safety.md", "reason": "Keep servlet-to-JSP display contracts explicit and null-safe."}
|
||||
{"file": ".trellis/spec/frontend/quality-guidelines.md", "reason": "Keep the report UI consistent with existing JSP pages."}
|
||||
{"file": ".trellis/spec/guides/cross-layer-thinking-guide.md", "reason": "Reports span DAO, service, servlet, JSP, and permissions."}
|
||||
{"file": ".trellis/tasks/archive/2026-04/00-bootstrap-guidelines/research/project-requirements.md", "reason": "Original project requirements include reports and statistics expectations."}
|
||||
@@ -0,0 +1,82 @@
|
||||
# 按顺序继续完成程序
|
||||
|
||||
## Goal
|
||||
|
||||
继续完成 MZH Library Management 的下一组核心功能,让现有 JSP + Servlet + JDBC 图书馆系统从已完成的基础业务链路继续向完整后台能力推进。
|
||||
|
||||
## What I already know
|
||||
|
||||
* 用户要求“按顺序继续完成程序”,当前没有 active task,因此本任务用于恢复开发方向并确认下一步范围。
|
||||
* 用户已选择下一步做 **报表中心**。
|
||||
* 项目是 Java 11 Maven WAR,使用 JSP + Servlet + MySQL/JDBC。
|
||||
* 已有认证、权限过滤、角色首页、图书目录、图书管理、读者管理、借书/还书/续借/逾期、读者借阅历史。
|
||||
* 最近提交顺序显示功能推进为:认证/权限 -> 图书 -> 读者 -> 借还续借逾期。
|
||||
* 数据库和权限模型中还预留了 `manage_users`、`view_reports`、`view_system_logs` 等能力。
|
||||
* 当前后台 Administration 卡片文案提到账号、角色、权限、系统维护入口,但实际还没有独立用户管理和系统日志页面。
|
||||
|
||||
## Assumptions (temporary)
|
||||
|
||||
* “按顺序”优先遵循现有业务链和权限模型:借阅链路完成后,应补齐统计报表或管理后台缺口。
|
||||
* 本轮应选择一个清晰、可验收的 MVP 模块,不把用户管理、报表、日志全部混在一次任务里。
|
||||
|
||||
## Open Questions
|
||||
|
||||
* None for this MVP.
|
||||
|
||||
## Requirements
|
||||
|
||||
* 继续沿用现有 Servlet -> Service -> DAO -> JSP 分层。
|
||||
* 新增报表中心,面向拥有 `view_reports` 权限的管理员和馆员。
|
||||
* 报表中心应至少展示:
|
||||
* 图书库存概览:总书目数、总册数、可借册数、不可借/归档或无可借库存的提示统计。
|
||||
* 借阅概览:当前借出、已归还、已逾期数量。
|
||||
* 逾期清单:展示读者、图书、应还日期、逾期天数等关键字段。
|
||||
* 热门借阅排行:按借阅记录数量展示 Top 图书。
|
||||
* 新页面入口应出现在 dashboard / role-home 的管理员和馆员工作区中。
|
||||
* 新功能必须接入现有角色权限体系;读者不能访问报表中心。
|
||||
* 新功能应包含 focused service checks,维持当前项目的轻量测试风格。
|
||||
* 报表数据应基于现有 `books`、`readers`、`borrow_records` 表,不引入新表。
|
||||
|
||||
## Acceptance Criteria
|
||||
|
||||
* [x] 明确下一步 MVP 模块:报表中心。
|
||||
* [x] 新模块有受权限保护的入口和页面。
|
||||
* [x] 新模块使用现有分层和错误处理风格。
|
||||
* [x] 管理员和馆员可打开报表中心,读者访问会被拒绝。
|
||||
* [x] 报表页面展示库存概览、借阅概览、逾期清单、热门借阅排行。
|
||||
* [x] 新增或更新服务层检查。
|
||||
* [ ] Maven 构建通过(当前环境未安装 `mvn`,已用 `javac` fallback 和轻量 checks 验证)。
|
||||
|
||||
## Definition of Done (team quality bar)
|
||||
|
||||
* Tests added/updated where appropriate.
|
||||
* Maven compile/package checks pass where available.
|
||||
* Docs/notes updated if behavior changes.
|
||||
* Rollout/rollback considered if risky.
|
||||
|
||||
## Out of Scope (explicit)
|
||||
|
||||
* 暂不一次性实现用户管理和系统日志页面。
|
||||
* 暂不实现图表库、导出 Excel/PDF、按日期筛选等高级报表能力。
|
||||
* 暂不引入新框架或前后端分离。
|
||||
* 暂不修改现有认证和核心借阅规则,除非所选模块必须依赖。
|
||||
|
||||
## Technical Approach
|
||||
|
||||
Add a reports slice consistent with the existing architecture: entity/value objects for report summaries, DAO queries for aggregate data, a service facade for report composition and permission checks, a servlet mapped to `/reports`, and a JSP under `WEB-INF/jsp/reports/`. Reuse existing CSS patterns for compact dashboard cards and tables.
|
||||
|
||||
## Decision (ADR-lite)
|
||||
|
||||
**Context**: The borrowing workflow is now implemented, and the permission model already contains `view_reports`.
|
||||
|
||||
**Decision**: Implement a server-rendered report center as the next MVP module, focused on operational summaries that can be derived from existing tables.
|
||||
|
||||
**Consequences**: This gives administrators and librarians immediate visibility into inventory and borrowing health without introducing reporting infrastructure. Date filters, exports, and charts remain future enhancements.
|
||||
|
||||
## Technical Notes
|
||||
|
||||
* `README.md` 描述当前项目结构和本地部署方式。
|
||||
* `src/main/resources/db/schema.sql` 已有 `system_logs` 表、`view_reports` 和 `view_system_logs` 权限。
|
||||
* `src/main/webapp/WEB-INF/web.xml` 当前未映射 reports、logs 或 users 管理 servlet。
|
||||
* `src/main/webapp/WEB-INF/jsp/dashboard.jsp` 和 `role-home.jsp` 是新增入口的主要位置。
|
||||
* 语义代码检索 MCP 返回 403 权限错误;本轮自动上下文改用本地只读文件检查。
|
||||
@@ -0,0 +1,26 @@
|
||||
{
|
||||
"id": "continue-program-sequence",
|
||||
"name": "continue-program-sequence",
|
||||
"title": "brainstorm: 按顺序继续完成程序",
|
||||
"description": "",
|
||||
"status": "in_progress",
|
||||
"dev_type": null,
|
||||
"scope": null,
|
||||
"package": null,
|
||||
"priority": "P2",
|
||||
"creator": "Zzzz",
|
||||
"assignee": "Zzzz",
|
||||
"createdAt": "2026-04-27",
|
||||
"completedAt": null,
|
||||
"branch": null,
|
||||
"base_branch": "master",
|
||||
"worktree_path": null,
|
||||
"commit": null,
|
||||
"pr_url": null,
|
||||
"subtasks": [],
|
||||
"children": [],
|
||||
"parent": null,
|
||||
"relatedFiles": [],
|
||||
"notes": "",
|
||||
"meta": {}
|
||||
}
|
||||
Reference in New Issue
Block a user