Skip to content

SCRUM-389 refactor(schedules): split apply-template handler into focused services - #365

Closed
Mahmoud-Alim wants to merge 1 commit into
mainfrom
refactor/apply-template-focused-services
Closed

Mahmoud-Alim wants to merge 1 commit into
mainfrom
refactor/apply-template-focused-services

Conversation

@Mahmoud-Alim

@Mahmoud-Alim Mahmoud-Alim commented Sep 15, 2026

Copy link
Copy Markdown
Collaborator

Summary

ApplyTemplateCommandHandler grew into an 876-line god handler with 10 dependencies
(availability + strip rules + overlap detection + keep policy + pricing + coverage
in one class). This PR extracts the logic into 5 focused services behind interfaces,
leaving the handler as a thin orchestrator (~169 lines, 5 dependencies).
No behavior change: same command, same response DTO, same strip/collision codes.

What Changed

Application Layer

  • New Features/Schedules/ApplyTemplate/Services/:
    ITemplateApplicationLoader (all data loading + persistence),
    IAvailabilityResolver (site authorization, operational hours, leave/remote),
    IEligibilityEvaluator (pure strip-rule evaluation, zero dependencies),
    IScheduleAnalyticsService (pure labor-cost + coverage calculation),
    IOverlapResolver (overlap detection + keep-new/keep-existing policy).
  • ApplyTemplateCommandHandler now only orchestrates: validate → load →
    availability → eligibility → overlaps → persist → analytics → response.
    Response mapping (BuildResponse/MapBlock) intentionally stays in the handler.
  • Inner classes (PlannedBlock, AvailabilityContext, KeepMode) promoted to
    standalone files. Backward-compatible obsolete constructor kept for transition.
  • DI registrations added in Application/DependencyInjection.cs.

Testing

  • Unit tests: existing ApplyTemplateTests (19 tests) updated to compose the new
    services; all pass. Full Schedules suite (186 tests) passes.
  • Integration tests: InMemory-backed handler tests cover strip codes, keep policies,
    overtime pricing, and coverage status.

Backward Compatibility

  • ApplyTemplateCommand and ApplyTemplateResponseDto are unchanged.
    Existing API clients are unaffected.

Important Implementation Details

  • Merge-order dependency: this branch alone does not compile against main,
    because the extracted services already use the specification-based repository API
    introduced in the follow-up branch refactor/decouple-application-from-ef-core.
    Merge this PR first, then the follow-up immediately after — or stack the
    follow-up onto this branch.
  • EligibilityEvaluator and ScheduleAnalyticsService are pure (no repositories)
    and are the best candidates for direct unit tests going forward.

Checklist

  • Build passes
  • Tests pass
  • No unintended breaking changes

Update (CI fix): to keep this PR self-contained and green standalone, it now also carries the minimal persistence foundation the new services need: Common/Specifications (ISpecification/Specification/PagedResult) plus the new spec-based IRepository/GenericRepository members. Backward compatibility is preserved — the old Query() member stays untouched and the new members ship as temporary default implementations (NotImplementedException) until SCRUM-390 turns them abstract and removes Query().

@vercel

vercel Bot commented Sep 15, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated
hr-system Ready Ready Preview Sep 15, 2026 9:45pm UTC

@Mahmoud-Alim Mahmoud-Alim changed the title refactor: split ApplyTemplate handler into focused services SCRUM-389 refactor(schedules): split apply-template handler into focused services Sep 15, 2026
@github-actions

Copy link
Copy Markdown

Automated PR Validation Feedback

Action Needed on this Pull Request:

  • Missing Jira Key: Please include your Jira key (e.g. SCRUM-6) in your PR title or branch name.
  • Code Formatting Failed: 16 changed C# file(s) do not match formatting rules. Run dotnet format locally on your changed files and commit the result.
  • Build Failure: The .NET 10 solution failed to compile or analyzers found errors. Run dotnet build locally and fix the issues.

Please push a fix to your branch to re-run validation!

@github-actions

Copy link
Copy Markdown

Automated PR Validation Feedback

Action Needed on this Pull Request:

  • Code Formatting Failed: 16 changed C# file(s) do not match formatting rules. Run dotnet format locally on your changed files and commit the result.
  • Build Failure: The .NET 10 solution failed to compile or analyzers found errors. Run dotnet build locally and fix the issues.

Please push a fix to your branch to re-run validation!

@github-actions

Copy link
Copy Markdown

Automated PR Validation Feedback

Action Needed on this Pull Request:

  • Code Formatting Failed: 19 changed C# file(s) do not match formatting rules. Run dotnet format locally on your changed files and commit the result.

Please push a fix to your branch to re-run validation!

1 similar comment
@github-actions

Copy link
Copy Markdown

Automated PR Validation Feedback

Action Needed on this Pull Request:

  • Code Formatting Failed: 19 changed C# file(s) do not match formatting rules. Run dotnet format locally on your changed files and commit the result.

Please push a fix to your branch to re-run validation!

@Moha-sami

Copy link
Copy Markdown
Owner

Declined: Adds excessive abstraction layers (5 new interfaces/classes for a single handler) and introduces specification pattern boilerplate. Existing CQRS handlers with direct repository/EF LINQ are simpler, more direct, and keep cognitive overhead low.

@Moha-sami Moha-sami closed this Sep 16, 2026
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.

2 participants