Skip to content

Commit b79e5a3

Browse files
committed
feat: implement work orders router
1 parent 1c1c134 commit b79e5a3

File tree

4 files changed

+292
-0
lines changed

4 files changed

+292
-0
lines changed
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
package com.ctrlhub.core.governance.schemes.workorders
2+
3+
import com.ctrlhub.core.Api
4+
import com.ctrlhub.core.governance.schemes.SchemesRouter
5+
import com.ctrlhub.core.governance.schemes.workorders.response.WorkOrder
6+
import com.ctrlhub.core.router.Router
7+
import io.ktor.client.HttpClient
8+
9+
class WorkOrdersRouter(httpClient: HttpClient) : Router(httpClient) {
10+
11+
/**
12+
* Retrieve a list of all schemes
13+
*
14+
* @param organisationId String The organisation ID to retrieve all schemes for
15+
* @param schemeId String The scheme ID to fetch all work orders for
16+
*
17+
* @return A list of all work orders
18+
*/
19+
suspend fun all(organisationId: String, schemeId: String): List<WorkOrder> {
20+
return fetchJsonApiResources("/v3/orgs/$organisationId/governance/schemes/$schemeId/work-orders")
21+
}
22+
23+
/**
24+
* Fetch a single work order by ID
25+
*
26+
* @param organisationId String The organisation ID to retrieve a single work order for
27+
* @param schemeId String The scheme ID to retrieve a single work order for
28+
* @param workOrderId String The work order ID to retrieve data for
29+
*
30+
* @return WorkOrder
31+
*/
32+
suspend fun one(organisationId: String, schemeId: String, workOrderId: String): WorkOrder {
33+
return fetchJsonApiResource("/v3/orgs/$organisationId/governance/schemes/$schemeId/work-orders/$workOrderId")
34+
}
35+
}
36+
37+
val Api.workOrders: WorkOrdersRouter
38+
get() = WorkOrdersRouter(httpClient)
39+
40+
val SchemesRouter.workOrders: WorkOrdersRouter
41+
get() = WorkOrdersRouter(httpClient)
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
package com.ctrlhub.core.governance.schemes.workorders
2+
3+
import com.ctrlhub.core.governance.schemes.workorders.response.WorkOrder
4+
import com.ctrlhub.core.configureForTest
5+
import io.ktor.client.HttpClient
6+
import io.ktor.client.engine.mock.MockEngine
7+
import io.ktor.client.engine.mock.respond
8+
import io.ktor.http.HttpHeaders
9+
import io.ktor.http.HttpStatusCode
10+
import io.ktor.http.headersOf
11+
import kotlinx.coroutines.runBlocking
12+
import org.junit.jupiter.api.Test
13+
import java.nio.file.Files
14+
import java.nio.file.Paths
15+
import kotlin.test.assertIs
16+
import kotlin.test.assertNotNull
17+
18+
class WorkOrdersRouterTest {
19+
20+
@Test
21+
fun `can retrieve all work orders for a scheme`() {
22+
val jsonFilePath = Paths.get("src/test/resources/governance/schemes/workorders/all-work-orders-response.json")
23+
val jsonContent = Files.readString(jsonFilePath)
24+
25+
val mockEngine = MockEngine { request ->
26+
respond(
27+
content = jsonContent,
28+
status = HttpStatusCode.OK,
29+
headers = headersOf(HttpHeaders.ContentType, "application/json")
30+
)
31+
}
32+
33+
val workOrdersRouter = WorkOrdersRouter(httpClient = HttpClient(mockEngine).configureForTest())
34+
35+
runBlocking {
36+
val response = workOrdersRouter.all(organisationId = "abc123", schemeId = "e3fbd3a4-4c96-4b97-8033-8a1a3b4c2e4c")
37+
38+
assertIs<List<WorkOrder>>(response)
39+
assertNotNull(response[0].id)
40+
}
41+
}
42+
43+
@Test
44+
fun `can retrieve a single work order by ID`() {
45+
val jsonFilePath = Paths.get("src/test/resources/governance/schemes/workorders/one-work-order-response.json")
46+
val jsonContent = Files.readString(jsonFilePath)
47+
48+
val mockEngine = MockEngine { request ->
49+
respond(
50+
content = jsonContent,
51+
status = HttpStatusCode.OK,
52+
headers = headersOf(HttpHeaders.ContentType, "application/json")
53+
)
54+
}
55+
56+
val workOrdersRouter = WorkOrdersRouter(httpClient = HttpClient(mockEngine).configureForTest())
57+
58+
runBlocking {
59+
val response = workOrdersRouter.one(
60+
organisationId = "abc123",
61+
schemeId = "e3fbd3a4-4c96-4b97-8033-8a1a3b4c2e4c",
62+
workOrderId = "b2d9c34f-57c4-4b93-8ef6-6342de1e1c3d"
63+
)
64+
65+
assertIs<WorkOrder>(response)
66+
assertNotNull(response.id)
67+
}
68+
}
69+
}
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
{
2+
"data": [
3+
{
4+
"id": "fcbf96d7-0a1b-48c1-87c7-c1bb556a7636",
5+
"type": "work-orders",
6+
"attributes": {
7+
"code": "xx.x.x",
8+
"description": null,
9+
"end_date": null,
10+
"labels": [],
11+
"name": "xx.x",
12+
"start_date": null
13+
},
14+
"relationships": {
15+
"operations": {
16+
"data": [
17+
{
18+
"id": "4e99c6f5-636b-4d1a-b06a-115a2d2f8eab",
19+
"type": "operations"
20+
},
21+
{
22+
"id": "53f3ac73-57b3-46a1-8fc6-bc81be9c4d63",
23+
"type": "operations"
24+
}
25+
]
26+
},
27+
"permits": {
28+
"data": []
29+
},
30+
"scheme": {
31+
"data": {
32+
"id": "33ac970f-f05e-4b7c-a358-ef6e8a4c9ea5",
33+
"type": "schemes"
34+
}
35+
}
36+
},
37+
"meta": {
38+
"completeness": {
39+
"percentage": {
40+
"completed": 0,
41+
"aborted": 0,
42+
"unknown": 100,
43+
"cancelled": 0
44+
},
45+
"counts": {
46+
"completed": 0,
47+
"aborted": 0,
48+
"unknown": 2,
49+
"cancelled": 0
50+
}
51+
},
52+
"counts": {
53+
"properties": 0,
54+
"streets": 0,
55+
"work_orders": 0,
56+
"operations": 2
57+
},
58+
"created_at": "2025-02-16T16:49:09Z",
59+
"updated_at": "2025-02-16T16:49:18Z",
60+
"modified_at": "2025-03-14T10:04:18Z"
61+
}
62+
}
63+
],
64+
"meta": {
65+
"features": {
66+
"params": {
67+
"include": {
68+
"options": [
69+
"scheme",
70+
"operations"
71+
]
72+
},
73+
"sort": {
74+
"default": "name",
75+
"options": [
76+
"name",
77+
"code",
78+
"created_at",
79+
"updated_at",
80+
"modified_at"
81+
]
82+
},
83+
"filter": {
84+
"options": null
85+
}
86+
}
87+
},
88+
"count": 1,
89+
"pagination": {
90+
"current_page": 1,
91+
"counts": {
92+
"resources": 1,
93+
"pages": 1
94+
},
95+
"requested": {
96+
"offset": 0,
97+
"limit": 100
98+
},
99+
"offsets": {
100+
"previous": null,
101+
"next": null
102+
}
103+
}
104+
},
105+
"jsonapi": {
106+
"version": "1.0",
107+
"meta": {}
108+
},
109+
"links": {
110+
"self": "https://api.ctrl-hub.dev/v3/orgs/92d8e9fc-874e-45ab-bab1-b68fd6181a94/governance/schemes/33ac970f-f05e-4b7c-a358-ef6e8a4c9ea5/work-orders"
111+
}
112+
}
Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
{
2+
"data": {
3+
"id": "b4cd0154-9e6f-442b-84d1-d1f1a888d2e4",
4+
"type": "work-orders",
5+
"attributes": {
6+
"code": "xx.1.x",
7+
"description": null,
8+
"end_date": null,
9+
"labels": [],
10+
"name": "xx.1",
11+
"start_date": null
12+
},
13+
"relationships": {
14+
"operations": {
15+
"data": [
16+
{
17+
"id": "9e2a4c21-6dbb-438d-8202-7505e2f12391",
18+
"type": "operations"
19+
},
20+
{
21+
"id": "bb7d5b49-c49e-4f17-9b99-5fd88fcd82fe",
22+
"type": "operations"
23+
}
24+
]
25+
},
26+
"permits": {
27+
"data": []
28+
},
29+
"scheme": {
30+
"data": {
31+
"id": "cf7a3628-bfe1-4d98-9a9f-eae6fa623d10",
32+
"type": "schemes"
33+
}
34+
}
35+
},
36+
"meta": {
37+
"completeness": {
38+
"percentage": {
39+
"completed": 0,
40+
"aborted": 0,
41+
"unknown": 100,
42+
"cancelled": 0
43+
},
44+
"counts": {
45+
"completed": 0,
46+
"aborted": 0,
47+
"unknown": 2,
48+
"cancelled": 0
49+
}
50+
},
51+
"counts": {
52+
"properties": 0,
53+
"streets": 0,
54+
"work_orders": 0,
55+
"operations": 2
56+
},
57+
"created_at": "2025-02-16T16:49:09Z",
58+
"updated_at": "2025-02-16T16:49:18Z",
59+
"modified_at": "2025-03-14T10:04:18Z"
60+
}
61+
},
62+
"meta": {},
63+
"jsonapi": {
64+
"version": "1.0",
65+
"meta": {}
66+
},
67+
"links": {
68+
"self": "https://api.ctrl-hub.dev/v3/orgs/50d04a88-e9be-4f7c-842a-e2b37b2fd2f1/governance/schemes/cf7a3628-bfe1-4d98-9a9f-eae6fa623d10/work-orders/b4cd0154-9e6f-442b-84d1-d1f1a888d2e4"
69+
}
70+
}

0 commit comments

Comments
 (0)