Skip to content

feat(reports): add BaseReport + 4 concrete report classes - #12

Merged
ldastey-dev merged 1 commit into
masterfrom
action/10-report-classes
Feb 22, 2026
Merged

feat(reports): add BaseReport + 4 concrete report classes#12
ldastey-dev merged 1 commit into
masterfrom
action/10-report-classes

Conversation

@ldastey-dev

Copy link
Copy Markdown
Owner

Action 10 — Report Classes

What this PR does

Introduces src/chesscom/reports/ — a layered report abstraction that replaces the business logic in all four legacy scripts.

Class hierarchy

BaseReport (ABC)
├── MemberSummaryReport      ← generate_club_member_report.py
├── ProspectReport           ← generate_prospect_data.py
├── MatchEligibilityReport   ← match_strengthening_extract.py
└── MatchParticipationReport ← club_contribution_report.py

BaseReport contract

Method Type Responsibility
collect_data() abstract Fetch + transform via ChessComClient
get_report_name() abstract Base filename / sheet name
build_sheet_configs(data) concrete (overridable) Maps data → SheetConfig list
run() concrete Orchestrates the pipeline, returns path

Report highlights

MemberSummaryReport — single sheet, Member.from_api_response for clean domain objects, joined timestamp passed from club-members endpoint.

ProspectReport — exclusion and deduplication at the raw-username level before fetching full profile/stats, avoiding wasted API calls for excluded members.

MatchEligibilityReport — uses filter_members_by_rating service; sheet name includes variant (CHESS / CHESS960); raises ValueError when match_id absent.

MatchParticipationReport — two-sheet workbook (Member Metrics + Match Data); uses build_participation_stats service; per-match result columns injected into Match Data sheet; raises ValueError when data_analysis_year absent.

All reports: no raw requests calls, no utils dependency, no module-level env vars.

Tests (41 new → 255 total)

Each report class has a dedicated test class using MagicMock for the client:

  • Report name, column presence, data accuracy
  • Exclusion / deduplication / filtering logic
  • Error paths (missing match_id, missing year)
  • build_sheet_configs sheet count / naming
  • run() integration tests using tmp_path

- src/chesscom/reports/base.py: abstract BaseReport with collect_data(),
  get_report_name(), overridable build_sheet_configs(), and concrete run()
- src/chesscom/reports/member_summary.py: MemberSummaryReport (replaces
  generate_club_member_report.py) — single sheet, Member.from_api_response
- src/chesscom/reports/prospect.py: ProspectReport (replaces
  generate_prospect_data.py) — username-level exclusion + dedup before
  expensive profile/stats fetch; no raw requests calls
- src/chesscom/reports/match_eligibility.py: MatchEligibilityReport
  (replaces match_strengthening_extract.py) — uses filter_members_by_rating
  service, dynamic sheet name with variant suffix
- src/chesscom/reports/match_participation.py: MatchParticipationReport
  (replaces club_contribution_report.py) — two-sheet workbook (Member
  Metrics + Match Data), uses build_participation_stats service
- All reports: ChessComClient for I/O, domain services for logic,
  ExcelReportWriter for output; no raw requests/utils calls
- 41 new unit tests (MagicMock client, tmp_path files); total 255
@ldastey-dev
ldastey-dev merged commit cd4595b into master Feb 22, 2026
2 checks passed
@ldastey-dev
ldastey-dev deleted the action/10-report-classes branch February 22, 2026 20:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant