Add leave update and dry-run support - #13
Merged
Merged
Conversation
There was a problem hiding this comment.
Pull request overview
Adds first-class leave update support to the TimePro CLI (tp leave update <ID>) and the MCP server (update_leave), including dry-run previews that validate and return the fully prepared API payload without writing changes. This fits the CLI’s pattern of providing safe, scriptable workflows (notably via --json and confirmation prompts) for TimePro operations.
Changes:
- Introduces shared
LeaveCreateService/LeaveUpdateServiceso CLI and MCP reuse the same validation + payload preparation logic. - Adds
tp leave update <ID>and extends leave create/update flows with--dry-run/dryRunpreviews. - Updates docs/templates/release notes and expands unit + integration coverage for leave update + dry-run behavior.
Reviewed changes
Copilot reviewed 18 out of 18 changed files in this pull request and generated 4 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/SSW.TimePro.Cli.Tests/Features/Updates/ReleaseNotesCatalogTests.cs | Bumps expected latest release version to 0.2.6. |
| tests/SSW.TimePro.Cli.Tests/Features/Mcp/LeaveMcpToolsTests.cs | Adds MCP tests for leave dry-run and update behavior + preserved fields. |
| tests/SSW.TimePro.Cli.Tests/Features/Leave/UpdateCommandTests.cs | New unit tests for tp leave update behavior, validation, and dry-run. |
| tests/SSW.TimePro.Cli.Tests/Features/Leave/CreateCommandTests.cs | Adds leave create dry-run test and registers LeaveCreateService in test DI. |
| tests/SSW.TimePro.Cli.Integration/Features/LeaveTests.cs | Adds integration coverage for update payload shape and optionalEmp mapping. |
| src/SSW.TimePro.Cli/Shared/Models/LeaveModels.cs | Extends leave DTO with OptionalEmp, UserStartTime, UserEndTime. |
| src/SSW.TimePro.Cli/Program.cs | Registers leave create/update services and adds the leave update command to CLI tree. |
| src/SSW.TimePro.Cli/Features/Skills/Templates/timepro-timesheets.md | Updates skill template examples to include leave update and dry-run usage. |
| src/SSW.TimePro.Cli/Features/Mcp/Tools/LeaveMcpTools.cs | Refactors MCP leave tools to use shared services; adds update_leave + dry-run. |
| src/SSW.TimePro.Cli/Features/Mcp/McpHostCommand.cs | Registers leave services in the MCP host DI container. |
| src/SSW.TimePro.Cli/Features/Leave/UpdateCommand.cs | New CLI command to update leave requests with confirmation + dry-run + JSON output. |
| src/SSW.TimePro.Cli/Features/Leave/LeaveUpdateService.cs | New service that rebuilds a full replacement update payload while preserving fields. |
| src/SSW.TimePro.Cli/Features/Leave/LeaveCreateService.cs | New service that centralizes leave-create validation + request building. |
| src/SSW.TimePro.Cli/Features/Leave/CreateCommand.cs | Refactors create command to use LeaveCreateService and adds --dry-run. |
| release-notes/0.2.6.md | Adds 0.2.6 release notes for leave update + dry-run. |
| README.md | Documents new update command + dry-run semantics and updates command inventory. |
| AGENTS.md | Updates canonical agent guidance for leave update + dry-run semantics. |
Suppressed comments (1)
src/SSW.TimePro.Cli/Features/Mcp/Tools/LeaveMcpTools.cs:156
- Same as
CreateLeave: this hand-crafts JSON for the not-logged-in case. PreferJsonSerializer.Serialize(..., JsonOpts)for consistent output formatting and escaping.
var tenant = _config.LoadActiveTenantConfig();
if (string.IsNullOrWhiteSpace(tenant?.EmployeeId))
return """{"error": "Not logged in. Run 'tp login --tenant <id>' first."}""";
Comment on lines
+36
to
+47
| if (string.IsNullOrWhiteSpace(options.Start) | ||
| || string.IsNullOrWhiteSpace(options.End) | ||
| || string.IsNullOrWhiteSpace(options.Type)) | ||
| { | ||
| throw new LeaveCreateValidationException("--start, --end, and --type are required"); | ||
| } | ||
|
|
||
| if (string.IsNullOrWhiteSpace(options.Note)) | ||
| { | ||
| throw new LeaveCreateValidationException( | ||
| "--note is required: a reason/description is mandatory for leave"); | ||
| } |
Comment on lines
+49
to
+53
| if (options.ClearApprovedBy && options.ApprovedBy is not null) | ||
| throw new LeaveUpdateValidationException("Use either approvedBy or clearApprovedBy, not both"); | ||
|
|
||
| if (options.ClearCc && options.Cc is not null) | ||
| throw new LeaveUpdateValidationException("Use either cc or clearCc, not both"); |
Comment on lines
101
to
104
| var tenant = _config.LoadActiveTenantConfig(); | ||
| if (tenant?.EmployeeId is null) | ||
| if (string.IsNullOrWhiteSpace(tenant?.EmployeeId)) | ||
| return """{"error": "Not logged in. Run 'tp login --tenant <id>' first."}"""; | ||
|
|
Comment on lines
+98
to
+103
| var tenant = _config.LoadActiveTenantConfig(); | ||
| if (tenant?.EmployeeId is null) | ||
| { | ||
| WriteValidationError(settings.Json, "Not logged in. Run 'tp login --tenant <id>' first."); | ||
| return 1; | ||
| } |
PothieuG
approved these changes
Aug 4, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
tp leave update <ID>with partial CLI options backed by TimePro's full replacement payloadupdate_leavetool--dry-run/dryRunsupport for both leave creation and leave updatesSafety and behavior
TimePro's leave update endpoint replaces the complete record. The update service first reads the existing leave, preserves API-returned fields that were not explicitly changed, validates the rebuilt request, and only then sends the update.
Dry-run performs the same reads, validation, and payload preparation but does not call the create or update endpoint. JSON dry-runs return the complete proposed request.
Older TimePro leave-list responses may omit stored workday start/end times. Updates preserve those fields when returned; otherwise they fall back to the current employee profile and then 09:00-18:00. Explicit
--start-timeand--end-timeremain available.Verification
dotnet test SSW.TimePro.Timesheets.Cli.slnx --no-restore- 284 passedgit diff --check- cleanScriban.Signed 7.2.0in the integration test project; this PR does not change package referencesCloses #12