Skip to content

Commit 1f20959

Browse files
committed
Detailed reports
1 parent 0b66bdd commit 1f20959

File tree

2 files changed

+324
-0
lines changed

2 files changed

+324
-0
lines changed
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
Import-Module -Name Pester -Force
2+
Import-Module .\Toggl.API\Toggl.API.psm1 -Force
3+
4+
$configPath = Join-Path -Path $PSScriptRoot -ChildPath "..\config.json"
5+
$config = Get-Content -Path $configPath | ConvertFrom-Json
6+
7+
$apiToken = $config.apiToken
8+
$workspaceId = $config.workspaceId
9+
10+
$startDate = "2023-01-01"
11+
$endDate = "2023-12-31"
12+
13+
Describe 'Reports.Detailed Integration Tests' {
14+
BeforeAll {
15+
$timeEntryIds = @()
16+
$tagIds = @()
17+
$start = [datetime]::ParseExact("2023-01-01", "yyyy-MM-dd", $null)
18+
$createdWith = "PesterTest"
19+
20+
# Create first time entry
21+
$response1 = New-TogglTimeEntry `
22+
-ApiToken $apiToken `
23+
-WorkspaceId $workspaceId `
24+
-CreatedWith $createdWith `
25+
-Start $start `
26+
-Description "Test Time Entry 1"
27+
28+
$response1 | Should Not BeNullOrEmpty
29+
$timeEntryIds += $response1.id
30+
31+
# Create second time entry
32+
$response2 = New-TogglTimeEntry `
33+
-ApiToken $apiToken `
34+
-WorkspaceId $workspaceId `
35+
-CreatedWith $createdWith `
36+
-Start $start `
37+
-Description "Test Time Entry 2"
38+
39+
$response2 | Should Not BeNullOrEmpty
40+
$timeEntryIds += $response2.id
41+
42+
$response3 = New-TogglTimeEntry `
43+
-ApiToken $apiToken `
44+
-WorkspaceId $workspaceId `
45+
-CreatedWith $createdWith `
46+
-Start $start `
47+
-Description "Test Time Entry 3" `
48+
-Tags @("tag1", "tag2")
49+
50+
$response3 | Should Not BeNullOrEmpty
51+
$timeEntryIds += $response3.id
52+
$tagIds += $response3.tag_ids
53+
}
54+
55+
AfterAll {
56+
foreach ($timeEntryId in $timeEntryIds) {
57+
Remove-TogglTimeEntry `
58+
-ApiToken $apiToken `
59+
-WorkspaceId $workspaceId `
60+
-TimeEntryId $timeEntryId
61+
}
62+
}
63+
64+
Context "Search-TogglTimeEntries" {
65+
It "should search for time entries with given filters" {
66+
67+
$response = Search-TogglTimeEntries `
68+
-ApiToken $apiToken `
69+
-WorkspaceId $workspaceId `
70+
-StartDate $startDate `
71+
-EndDate $endDate `
72+
-PageSize 10
73+
74+
$response | Should Not BeNullOrEmpty
75+
$response.GetType().Name | Should -Be "Object[]"
76+
$response.Count | Should -BeExactly $timeEntryIds.Count
77+
78+
$response | ForEach-Object {
79+
$_.description | Should -Match "Test Time Entry"
80+
}
81+
82+
$response.time_entries.id | ForEach-Object {
83+
$timeEntryIds | Should -Contain $_
84+
}
85+
}
86+
87+
It "should search for time entries without tags" {
88+
$response = Search-TogglTimeEntries `
89+
-ApiToken $apiToken `
90+
-WorkspaceId $workspaceId `
91+
-StartDate $startDate `
92+
-EndDate $endDate `
93+
-TagIds @() `
94+
-PageSize 10
95+
96+
$response | Should Not BeNullOrEmpty
97+
$response.GetType().Name | Should -Be "Object[]"
98+
99+
$response | ForEach-Object {
100+
$_.tags | Should BeNullOrEmpty
101+
}
102+
}
103+
104+
It "should search for time entries with tags" {
105+
$response = Search-TogglTimeEntries `
106+
-ApiToken $apiToken `
107+
-WorkspaceId $workspaceId `
108+
-StartDate $startDate `
109+
-EndDate $endDate `
110+
-TagIds $tagIds `
111+
-PageSize 10
112+
113+
$response | Should Not BeNullOrEmpty
114+
115+
$response.GetType().Name | Should -Be "PSCustomObject"
116+
117+
$response.tag_ids | Should -BeExactly $tagIds
118+
}
119+
}
120+
}
Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
<#
2+
.SYNOPSIS
3+
Returns time entries for detailed report according to the given filters.
4+
5+
.DESCRIPTION
6+
This cmdlet retrieves time entries for a detailed report from Toggl using the provided parameters. It sends a POST request to the Toggl API.
7+
8+
.PARAMETER ApiToken
9+
The API token for authentication. (Mandatory)
10+
11+
.PARAMETER WorkspaceId
12+
Numeric ID of the workspace. (Mandatory)
13+
14+
.PARAMETER Billable
15+
Whether the time entry is set as billable, optional, premium feature. (Optional)
16+
17+
.PARAMETER ClientIds
18+
Client IDs, optional, filtering attribute. To filter records with no clients, use [null]. (Optional)
19+
20+
.PARAMETER Description
21+
Description, optional, filtering attribute. (Optional)
22+
23+
.PARAMETER EndDate
24+
End date, example time.DateOnly. Should be greater than Start date. (Optional)
25+
26+
.PARAMETER EnrichResponse
27+
EnrichResponse, optional, default false. It will force the detailed report to return as much information as possible, as it does for the export. (Optional)
28+
29+
.PARAMETER FirstId
30+
(Optional)
31+
32+
.PARAMETER FirstRowNumber
33+
(Optional)
34+
35+
.PARAMETER FirstTimestamp
36+
(Optional)
37+
38+
.PARAMETER GroupIds
39+
Group IDs, optional, filtering attribute. (Optional)
40+
41+
.PARAMETER Grouped
42+
Whether time entries should be grouped, optional, default false. (Optional)
43+
44+
.PARAMETER HideAmounts
45+
Whether amounts should be hidden, optional, default false. (Optional)
46+
47+
.PARAMETER MaxDurationSeconds
48+
Max duration seconds, optional, filtering attribute. Time Audit only, should be greater than MinDurationSeconds. (Optional)
49+
50+
.PARAMETER MinDurationSeconds
51+
Min duration seconds, optional, filtering attribute. Time Audit only, should be less than MaxDurationSeconds. (Optional)
52+
53+
.PARAMETER OrderBy
54+
Order by field, optional, default "date". Can be "date", "user", "duration", "description" or "last_update". (Optional)
55+
56+
.PARAMETER OrderDir
57+
Order direction, optional. Can be ASC or DESC. (Optional)
58+
59+
.PARAMETER PageSize
60+
PageSize defines the number of items per page, optional, default 50. (Optional)
61+
62+
.PARAMETER ProjectIds
63+
Project IDs, optional, filtering attribute. To filter records with no projects, use [null]. (Optional)
64+
65+
.PARAMETER Rounding
66+
Whether time should be rounded, optional, default from user preferences. (Optional)
67+
68+
.PARAMETER RoundingMinutes
69+
Rounding minutes value, optional, default from user preferences. Should be 0, 1, 5, 6, 10, 12, 15, 30, 60 or 240. (Optional)
70+
71+
.PARAMETER StartTime
72+
(Optional)
73+
74+
.PARAMETER StartDate
75+
Start date, example time.DateOnly. Should be less than End date. (Optional)
76+
77+
.PARAMETER TagIds
78+
Tag IDs, optional, filtering attribute. To filter records with no tags, use [null]. (Optional)
79+
80+
.PARAMETER TaskIds
81+
Task IDs, optional, filtering attribute. To filter records with no tasks, use [null]. (Optional)
82+
83+
.PARAMETER TimeEntryIds
84+
TimeEntryIDs filters by time entries. This was added to support retro-compatibility with reports v2. (Optional)
85+
86+
.PARAMETER UserIds
87+
User IDs, optional, filtering attribute. (Optional)
88+
89+
.EXAMPLE
90+
Search-TogglTimeEntries -ApiToken "your_api_token" -WorkspaceId 123456 -StartDate "2023-01-01" -EndDate "2023-12-31"
91+
#>
92+
function Search-TogglTimeEntries {
93+
[CmdletBinding()]
94+
param (
95+
[Parameter(Mandatory = $true)]
96+
[string]$ApiToken,
97+
98+
[Parameter(Mandatory = $true)]
99+
[int]$WorkspaceId,
100+
101+
[bool]$Billable,
102+
103+
[int[]]$ClientIds,
104+
105+
[string]$Description,
106+
107+
[string]$EndDate,
108+
109+
[bool]$EnrichResponse = $false,
110+
111+
[int]$FirstId,
112+
113+
[int]$FirstRowNumber,
114+
115+
[int]$FirstTimestamp,
116+
117+
[int[]]$GroupIds,
118+
119+
[bool]$Grouped = $false,
120+
121+
[bool]$HideAmounts = $false,
122+
123+
[int]$MaxDurationSeconds,
124+
125+
[int]$MinDurationSeconds,
126+
127+
[string]$OrderBy = "date",
128+
129+
[string]$OrderDir = "asc",
130+
131+
[int]$PageSize = 50,
132+
133+
[int[]]$ProjectIds,
134+
135+
[int]$Rounding,
136+
137+
[int]$RoundingMinutes,
138+
139+
[string]$StartTime,
140+
141+
[string]$StartDate,
142+
143+
[int[]]$TagIds,
144+
145+
[int[]]$TaskIds,
146+
147+
[int[]]$TimeEntryIds,
148+
149+
[int[]]$UserIds
150+
)
151+
152+
$url = "$Global:TogglReportsBaseUrl/workspace/$WorkspaceId/search/time_entries"
153+
154+
$body = @{}
155+
156+
if ($PSBoundParameters.ContainsKey('Billable')) { $body.billable = $Billable }
157+
if ($PSBoundParameters.ContainsKey('ClientIds')) { $body.client_ids = $ClientIds }
158+
if ($PSBoundParameters.ContainsKey('Description')) { $body.description = $Description }
159+
if ($PSBoundParameters.ContainsKey('EndDate')) { $body.end_date = $EndDate }
160+
if ($PSBoundParameters.ContainsKey('EnrichResponse')) { $body.enrich_response = $EnrichResponse }
161+
if ($PSBoundParameters.ContainsKey('FirstId')) { $body.first_id = $FirstId }
162+
if ($PSBoundParameters.ContainsKey('FirstRowNumber')) { $body.first_row_number = $FirstRowNumber }
163+
if ($PSBoundParameters.ContainsKey('FirstTimestamp')) { $body.first_timestamp = $FirstTimestamp }
164+
if ($PSBoundParameters.ContainsKey('GroupIds')) { $body.group_ids = $GroupIds }
165+
if ($PSBoundParameters.ContainsKey('Grouped')) { $body.grouped = $Grouped }
166+
if ($PSBoundParameters.ContainsKey('HideAmounts')) { $body.hide_amounts = $HideAmounts }
167+
if ($PSBoundParameters.ContainsKey('MaxDurationSeconds')) { $body.max_duration_seconds = $MaxDurationSeconds }
168+
if ($PSBoundParameters.ContainsKey('MinDurationSeconds')) { $body.min_duration_seconds = $MinDurationSeconds }
169+
if ($PSBoundParameters.ContainsKey('OrderBy')) { $body.order_by = $OrderBy }
170+
if ($PSBoundParameters.ContainsKey('OrderDir')) { $body.order_dir = $OrderDir }
171+
if ($PSBoundParameters.ContainsKey('PageSize')) { $body.page_size = $PageSize }
172+
if ($PSBoundParameters.ContainsKey('ProjectIds')) { $body.project_ids = $ProjectIds }
173+
if ($PSBoundParameters.ContainsKey('Rounding')) { $body.rounding = $Rounding }
174+
if ($PSBoundParameters.ContainsKey('RoundingMinutes')) { $body.rounding_minutes = $RoundingMinutes }
175+
if ($PSBoundParameters.ContainsKey('StartTime')) { $body.start_time = $StartTime }
176+
if ($PSBoundParameters.ContainsKey('StartDate')) { $body.start_date = $StartDate }
177+
if ($PSBoundParameters.ContainsKey('TagIds')) {
178+
if ($TagIds.Count -eq 0) {
179+
$body.tag_ids = @($null)
180+
}
181+
else {
182+
$body.tag_ids = $TagIds
183+
}
184+
}
185+
if ($PSBoundParameters.ContainsKey('TaskIds')) { $body.task_ids = $TaskIds }
186+
if ($PSBoundParameters.ContainsKey('TimeEntryIds')) { $body.time_entry_ids = $TimeEntryIds }
187+
if ($PSBoundParameters.ContainsKey('UserIds')) { $body.user_ids = $UserIds }
188+
189+
$jsonBody = $body | ConvertTo-Json -Compress -Depth 10
190+
Write-Host $jsonBody
191+
192+
$headers = Get-TogglAuthHeader -ApiToken $ApiToken
193+
$headers.Add("Content-Type", "application/json")
194+
195+
try {
196+
$response = Invoke-RestMethod -Uri $url -Method Post -Headers $headers -Body $jsonBody
197+
return $response
198+
}
199+
catch {
200+
Write-Error "Failed to fetch detailed reports: $_"
201+
}
202+
}
203+
204+
Export-ModuleMember -Function Search-TogglTimeEntries

0 commit comments

Comments
 (0)