2026-05-13-report-business-footer.md 7.6 KB

Report Business Footer Implementation Plan

For agentic workers: REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (- [ ]) syntax for tracking.

Goal: Add optional BusinessInfo support to both exam sprint reports, show concrete report type text in repeated headers, and render business contact info on the left side of repeated footers with page numbers on the right.

Architecture: Extend report payload contracts with a shared optional BusinessInfo record. Renderers own business-data formatting by emitting .report-footer-business markup, while DefaultPlaywrightPdfWorker extracts that markup into Chromium's native footer template next to the page-number placeholders. Existing native page header/footer margin handling remains unchanged.

Tech Stack: Java records, Jackson JSON binding, Bean Validation annotations, HTML templates, Playwright Java PDF header/footer templates, JUnit 5, AssertJ, PDFBox.


File Map

  • Create abilities/exam-sprint/contracts/src/main/java/cn/yunzhixue/ability/center/examsprint/contracts/report/BusinessInfo.java: shared optional payload object.
  • Modify AchievementExamSprintReportPayload.java: add BusinessInfo businessInfo field.
  • Modify OutlookExamSprintReportPayload.java: add BusinessInfo businessInfo field.
  • Modify AchievementReportContent.java: add nested optional domain BusinessInfo and compact constructor normalization.
  • Modify AchievementReportContentMapper.java: map payload business info to domain content.
  • Modify achievement/outlook HTML templates: replace fixed header type placeholder and add optional footer business placeholder.
  • Modify achievement/outlook renderers: provide report type placeholder and footer business markup.
  • Modify DefaultPlaywrightPdfWorker.java: extract optional footer business block and place it left of right-aligned page numbers.
  • Modify tests under application and infrastructure to cover new behavior.

Task 1: Contract and Domain BusinessInfo Flow

Files:

  • Create: abilities/exam-sprint/contracts/src/main/java/cn/yunzhixue/ability/center/examsprint/contracts/report/BusinessInfo.java
  • Modify: abilities/exam-sprint/contracts/src/main/java/cn/yunzhixue/ability/center/examsprint/contracts/report/AchievementExamSprintReportPayload.java
  • Modify: abilities/exam-sprint/contracts/src/main/java/cn/yunzhixue/ability/center/examsprint/contracts/report/OutlookExamSprintReportPayload.java
  • Modify: abilities/exam-sprint/domain/src/main/java/cn/yunzhixue/ability/center/examsprint/domain/report/AchievementReportContent.java
  • Modify: abilities/exam-sprint/application/src/main/java/cn/yunzhixue/ability/center/examsprint/application/report/AchievementReportContentMapper.java
  • Test: abilities/exam-sprint/application/src/test/java/cn/yunzhixue/ability/center/examsprint/application/report/AchievementReportContentMapperTest.java

  • [ ] Step 1: Write failing mapper test

Add a test that parses an achievement payload with BusinessInfo, maps it, and asserts businessInfo().name(), phone(), and address() are populated.

  • Step 2: Run mapper test to verify RED

Run: mvn -pl abilities/exam-sprint/application -Dtest=AchievementReportContentMapperTest test Expected: compilation failure or assertion failure because BusinessInfo is not modeled yet.

  • Step 3: Add contracts and domain fields

Create BusinessInfo contract record and add optional fields to both payload records. Add AchievementReportContent.BusinessInfo and a nullable businessInfo component.

  • Step 4: Map achievement business info

Update AchievementReportContentMapper.toDomainContent to convert non-null payload business info to domain business info.

  • Step 5: Run mapper test to verify GREEN

Run: mvn -pl abilities/exam-sprint/application -Dtest=AchievementReportContentMapperTest test Expected: PASS.

Task 2: Renderer Header Type and Footer Business Markup

Files:

  • Modify: abilities/exam-sprint/infrastructure/src/main/resources/templates/achievement-exam-sprint-report-template.html
  • Modify: abilities/exam-sprint/infrastructure/src/main/resources/templates/outlook-exam-sprint-report-template.html
  • Modify: abilities/exam-sprint/infrastructure/src/main/java/cn/yunzhixue/ability/center/examsprint/infrastructure/report/rendering/achievement/ClasspathAchievementExamSprintReportRenderer.java
  • Modify: abilities/exam-sprint/infrastructure/src/main/java/cn/yunzhixue/ability/center/examsprint/infrastructure/report/rendering/outlook/ClasspathOutlookExamSprintReportRenderer.java
  • Test: achievement/outlook renderer tests.

  • [ ] Step 1: Write failing renderer tests

Assert achievement header contains 学习成果报告; outlook header contains 潜力展望报告; business info renders in .report-footer-business when present and does not render when missing.

  • Step 2: Run renderer tests to verify RED

Run: mvn -pl abilities/exam-sprint/infrastructure -Dtest=ClasspathAchievementExamSprintReportRendererTest,ClasspathOutlookExamSprintReportRendererTest test Expected: FAIL because templates still contain fixed header text and no footer business markup.

  • Step 3: Implement renderer placeholders

Replace fixed header report type text with {{headerReportType}}. Add {{reportFooterBusiness}} before </body>. Render escaped optional business markup with first line name/phone and second line address.

  • Step 4: Run renderer tests to verify GREEN

Run: mvn -pl abilities/exam-sprint/infrastructure -Dtest=ClasspathAchievementExamSprintReportRendererTest,ClasspathOutlookExamSprintReportRendererTest test Expected: PASS.

Task 3: PDF Footer Layout Extraction

Files:

  • Modify: abilities/exam-sprint/infrastructure/src/main/java/cn/yunzhixue/ability/center/examsprint/infrastructure/report/pdf/DefaultPlaywrightPdfWorker.java
  • Test: abilities/exam-sprint/infrastructure/src/test/java/cn/yunzhixue/ability/center/examsprint/infrastructure/report/pdf/PlaywrightExamSprintReportPdfGeneratorTest.java

  • [ ] Step 1: Write failing PDF footer test

Generate multi-page HTML containing .report-footer-business, then use PDFBox text positions to assert business text is on the left half of the page and 2 / total is on the right half.

  • Step 2: Run PDF footer test to verify RED

Run: mvn -pl abilities/exam-sprint/infrastructure -Dtest=PlaywrightExamSprintReportPdfGeneratorTest#generatePlacesBusinessInfoLeftAndPageNumbersRightInFooter test Expected: FAIL because footer template currently only renders centered page numbers.

  • Step 3: Implement footer extraction

Add a .report-footer-business regex extractor, remove that source block from print body HTML, and build a footer template with left business block and right page-number block.

  • Step 4: Run PDF footer test to verify GREEN

Run: mvn -pl abilities/exam-sprint/infrastructure -Dtest=PlaywrightExamSprintReportPdfGeneratorTest#generatePlacesBusinessInfoLeftAndPageNumbersRightInFooter test Expected: PASS.

Task 4: Full Verification

Files:

  • No additional production files.

  • [ ] Step 1: Run contract/application relevant tests

Run: mvn -pl abilities/exam-sprint/application test Expected: PASS.

  • Step 2: Run infrastructure tests

Run: mvn -pl abilities/exam-sprint/infrastructure test Expected: PASS.

  • Step 3: Review diff

Run: git diff -- abilities/exam-sprint docs/superpowers/specs/2026-05-13-report-business-footer-design.md docs/superpowers/plans/2026-05-13-report-business-footer.md Expected: only intended contract, mapper, renderer, template, PDF worker, test, and documentation changes.