Skip to content

Commit 2753454

Browse files
committed
feat: support equipment exposures
1 parent a95549f commit 2753454

File tree

6 files changed

+363
-4
lines changed

6 files changed

+363
-4
lines changed
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
package com.ctrlhub.core.assets.equipment.exposures
2+
3+
import com.ctrlhub.core.assets.equipment.EquipmentRouter
4+
import com.ctrlhub.core.assets.equipment.exposures.resource.EquipmentExposureResource
5+
import com.ctrlhub.core.router.Router
6+
import com.ctrlhub.core.router.request.FilterOption
7+
import com.ctrlhub.core.router.request.JsonApiIncludes
8+
import com.ctrlhub.core.router.request.RequestParametersWithIncludes
9+
import io.ktor.client.HttpClient
10+
11+
enum class EquipmentExposureIncludes(val value: String) : JsonApiIncludes {
12+
Equipment("equipment"),
13+
EquipmentModel("equipment.model"),
14+
EquipmentModelManufacturer("equipment.model.manufacturer"),
15+
EquipmentModelCategories("equipment.model.categories");
16+
17+
override fun value(): String {
18+
return value
19+
}
20+
}
21+
22+
class EquipmentExposureRequestParameters(
23+
filterOptions: List<FilterOption> = emptyList(),
24+
includes: List<EquipmentExposureIncludes> = emptyList()
25+
) : RequestParametersWithIncludes<EquipmentExposureIncludes>(filterOptions, includes)
26+
27+
/**
28+
* An equipment exposure router that deals with the exposures realm of the Ctrl Hub API
29+
*/
30+
class EquipmentExposuresRouter(httpClient: HttpClient) : Router(httpClient) {
31+
32+
/**
33+
* Request all equipment exposures
34+
*
35+
* @param organisationId String The organisation ID to retrieve all exposure records for
36+
* @param equipmentId String The equipment ID to retrieve all exposure records for
37+
* @param requestParameters RequestParameters An instance of EquipmentExposureRequestParameters, capturing sorting, filtering and pagination based request params
38+
*
39+
* @return A list of all equipment exposures
40+
*/
41+
suspend fun all(
42+
organisationId: String,
43+
equipmentId: String,
44+
requestParameters: EquipmentExposureRequestParameters = EquipmentExposureRequestParameters()
45+
): List<EquipmentExposureResource> {
46+
return fetchJsonApiResources(
47+
"/v3/orgs/$organisationId/assets/equipment/$equipmentId/exposures",
48+
requestParameters.toMap()
49+
)
50+
}
51+
52+
/**
53+
* Request a single equipment exposures
54+
*
55+
* @param organisationId String The organisation ID to retrieve all exposure records for
56+
* @param equipmentId String The equipment ID to retrieve all exposure records for
57+
* @param exposureId String The exposure ID record to retrieve
58+
* @param requestParameters RequestParameters An instance of EquipmentExposureRequestParameters, capturing sorting, filtering and pagination based request params
59+
*
60+
* @return A list of all equipment exposures
61+
*/
62+
suspend fun one(
63+
organisationId: String,
64+
equipmentId: String,
65+
exposureId: String,
66+
requestParameters: EquipmentExposureRequestParameters = EquipmentExposureRequestParameters()
67+
): EquipmentExposureResource {
68+
return fetchJsonApiResource(
69+
"/v3/orgs/$organisationId/assets/equipment/$equipmentId/exposures/$exposureId",
70+
requestParameters.toMap()
71+
)
72+
}
73+
74+
/**
75+
* Create a new equipment exposure record
76+
*
77+
* @param organisationId String The organisation ID to retrieve all exposure records for
78+
* @param equipmentId String The equipment ID to retrieve all exposure records for
79+
* @param resource EquipmentExposureResource The resource to create
80+
*
81+
* @return A list of all equipment exposures
82+
*/
83+
suspend fun create(
84+
organisationId: String,
85+
equipmentId: String,
86+
resource: EquipmentExposureResource
87+
): EquipmentExposureResource {
88+
return postJsonApiResource("/v3/orgs/$organisationId/assets/equipment/$equipmentId/exposures", resource)
89+
}
90+
}
91+
92+
val EquipmentRouter.exposures: EquipmentExposuresRouter
93+
get() = EquipmentExposuresRouter(httpClient)
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package com.ctrlhub.core.assets.equipment.exposures.resource
2+
3+
import com.fasterxml.jackson.annotation.JsonCreator
4+
import com.fasterxml.jackson.annotation.JsonIgnoreProperties
5+
import com.fasterxml.jackson.annotation.JsonProperty
6+
import com.github.jasminb.jsonapi.StringIdHandler
7+
import com.github.jasminb.jsonapi.annotations.Id
8+
import com.github.jasminb.jsonapi.annotations.Meta
9+
import com.github.jasminb.jsonapi.annotations.Type
10+
import java.time.LocalDateTime
11+
12+
@Type("equipment-exposures")
13+
@JsonIgnoreProperties(ignoreUnknown = true)
14+
class EquipmentExposureResource @JsonCreator constructor(
15+
@JsonProperty("id") @Id(StringIdHandler::class) var id: String = "",
16+
@JsonProperty("start_time") var startTime: LocalDateTime? = null,
17+
@JsonProperty("end_time") var endTime: LocalDateTime? = null,
18+
@JsonProperty("ppe") var ppe: EquipmentExposurePpe? = EquipmentExposurePpe(),
19+
20+
@Meta var meta: EquipmentExposureMeta = EquipmentExposureMeta()
21+
)
22+
23+
class EquipmentExposurePpe @JsonCreator constructor(
24+
@JsonProperty("mask") var mask: Boolean?,
25+
@JsonProperty("ear_defenders") var earDefenders: Boolean?
26+
) {
27+
constructor(): this(
28+
mask = null,
29+
earDefenders = null
30+
)
31+
}
32+
33+
class EquipmentExposureMeta @JsonCreator constructor(
34+
@JsonProperty("created_at") var createdAt: LocalDateTime? = null,
35+
@JsonProperty("trigger_time") var triggerTime: Int? = null,
36+
@JsonProperty("havs") var havs: EquipmentExposureHavsExposureValues = EquipmentExposureHavsExposureValues(),
37+
) {
38+
constructor(): this(
39+
createdAt = null,
40+
triggerTime = null,
41+
havs = EquipmentExposureHavsExposureValues()
42+
)
43+
}
44+
45+
class EquipmentExposureHavsExposureValues @JsonCreator constructor(
46+
@JsonProperty var points: Int? = null,
47+
@JsonProperty var a8: Double? = null
48+
) {
49+
constructor(): this(
50+
points = null,
51+
a8 = null
52+
)
53+
}

src/test/kotlin/com/ctrlhub/core/assets/equipment/EquipmentRouterTest.kt

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
package com.ctrlhub.core.assets.equipment
22

33
import com.ctrlhub.core.assets.equipment.resource.EquipmentItem
4-
import com.ctrlhub.core.assets.vehicles.VehicleIncludes
5-
import com.ctrlhub.core.assets.vehicles.VehicleRequestParameters
6-
import com.ctrlhub.core.assets.vehicles.VehiclesRouter
7-
import com.ctrlhub.core.assets.vehicles.resource.Vehicle
84
import com.ctrlhub.core.configureForTest
95
import io.ktor.client.HttpClient
106
import io.ktor.client.engine.mock.MockEngine
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
package com.ctrlhub.core.assets.equipment.exposures
2+
3+
import com.ctrlhub.core.assets.equipment.exposures.resource.EquipmentExposureResource
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 EquipmentExposuresRouterTest {
19+
@Test
20+
fun `can retrieve all equipment exposures`() {
21+
val jsonFilePath = Paths.get("src/test/resources/assets/equipment/exposures/all-exposures-response.json")
22+
val jsonContent = Files.readString(jsonFilePath)
23+
24+
val mockEngine = MockEngine { request ->
25+
respond(
26+
content = jsonContent,
27+
status = HttpStatusCode.OK,
28+
headers = headersOf(HttpHeaders.ContentType, "application/json")
29+
)
30+
}
31+
32+
val exposuresRouter = EquipmentExposuresRouter(httpClient = HttpClient(mockEngine).configureForTest())
33+
34+
runBlocking {
35+
val response = exposuresRouter.all(organisationId = "000", equipmentId = "000")
36+
assertIs<List<EquipmentExposureResource>>(response)
37+
assertNotNull(response[0].id)
38+
}
39+
}
40+
41+
@Test
42+
fun `can retrieve one equipment exposure`() {
43+
val jsonFilePath = Paths.get("src/test/resources/assets/equipment/exposures/one-exposure-response.json")
44+
val jsonContent = Files.readString(jsonFilePath)
45+
46+
val mockEngine = MockEngine { request ->
47+
respond(
48+
content = jsonContent,
49+
status = HttpStatusCode.OK,
50+
headers = headersOf(HttpHeaders.ContentType, "application/json")
51+
)
52+
}
53+
54+
val exposuresRouter = EquipmentExposuresRouter(httpClient = HttpClient(mockEngine).configureForTest())
55+
56+
runBlocking {
57+
val response = exposuresRouter.one(organisationId = "000", equipmentId = "000", exposureId = "000")
58+
assertIs<EquipmentExposureResource>(response)
59+
assertNotNull(response.id)
60+
}
61+
}
62+
}
Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
{
2+
"data": [
3+
{
4+
"id": "00000000-0000-0000-0000-000000000000",
5+
"type": "equipment-exposures",
6+
"attributes": {
7+
"end_time": "2024-11-13T19:13:00Z",
8+
"location": null,
9+
"ppe": {
10+
"mask": true,
11+
"ear_defenders": false
12+
},
13+
"start_time": "2024-11-13T17:48:00Z"
14+
},
15+
"relationships": {
16+
"author": {
17+
"data": null
18+
},
19+
"equipment": {
20+
"data": {
21+
"id": "00000000-0000-0000-0000-000000000000",
22+
"type": "equipment-items"
23+
}
24+
}
25+
},
26+
"meta": {
27+
"created_at": "2024-12-19T21:05:41Z",
28+
"trigger_time": 85,
29+
"havs": {
30+
"points": 18,
31+
"a8": 1.0520317644127166
32+
}
33+
}
34+
},
35+
{
36+
"id": "00000000-0000-0000-0000-000000000000",
37+
"type": "equipment-exposures",
38+
"attributes": {
39+
"end_time": "2024-11-13T19:13:00Z",
40+
"location": null,
41+
"ppe": {
42+
"mask": true,
43+
"ear_defenders": false
44+
},
45+
"start_time": "2024-11-13T17:48:00Z"
46+
},
47+
"relationships": {
48+
"author": {
49+
"data": null
50+
},
51+
"equipment": {
52+
"data": {
53+
"id": "00000000-0000-0000-0000-000000000000",
54+
"type": "equipment-items"
55+
}
56+
}
57+
},
58+
"meta": {
59+
"created_at": "2024-12-19T21:07:14Z",
60+
"trigger_time": 85,
61+
"havs": {
62+
"points": 18,
63+
"a8": 1.0520317644127166
64+
}
65+
}
66+
}
67+
],
68+
"meta": {
69+
"features": {
70+
"params": {
71+
"include": {
72+
"options": [
73+
"author",
74+
"equipment",
75+
"equipment.model",
76+
"equipment.model.manufacturer",
77+
"equipment.model.categories"
78+
]
79+
},
80+
"sort": {
81+
"default": "",
82+
"options": null
83+
},
84+
"filter": {
85+
"options": null
86+
}
87+
}
88+
},
89+
"count": 7,
90+
"pagination": {
91+
"current_page": 1,
92+
"counts": {
93+
"resources": 7,
94+
"pages": 1
95+
},
96+
"requested": {
97+
"offset": 0,
98+
"limit": 100
99+
},
100+
"offsets": {
101+
"previous": null,
102+
"next": null
103+
}
104+
}
105+
},
106+
"jsonapi": {
107+
"version": "1.0",
108+
"meta": {}
109+
},
110+
"links": {
111+
"self": "https://api.ctrl-hub.dev/v3/orgs/00000000-0000-0000-0000-000000000000/assets/equipment/00000000-0000-0000-0000-000000000000/exposures"
112+
}
113+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
{
2+
"data": {
3+
"id": "00000000-0000-0000-0000-000000000000",
4+
"type": "equipment-exposures",
5+
"attributes": {
6+
"end_time": "2024-11-13T19:13:00Z",
7+
"location": null,
8+
"ppe": {
9+
"mask": true,
10+
"ear_defenders": false
11+
},
12+
"start_time": "2024-11-13T17:48:00Z"
13+
},
14+
"relationships": {
15+
"author": {
16+
"data": null
17+
},
18+
"equipment": {
19+
"data": {
20+
"id": "00000000-0000-0000-0000-000000000000",
21+
"type": "equipment-items"
22+
}
23+
}
24+
},
25+
"meta": {
26+
"created_at": "2024-12-19T21:05:41Z",
27+
"trigger_time": 85,
28+
"havs": {
29+
"points": 18,
30+
"a8": 1.0520317644127166
31+
}
32+
}
33+
},
34+
"meta": {},
35+
"jsonapi": {
36+
"version": "1.0",
37+
"meta": {}
38+
},
39+
"links": {
40+
"self": "https://api.ctrl-hub.dev/v3/orgs/00000000-0000-0000-0000-000000000000/assets/equipment/00000000-0000-0000-0000-000000000000/exposures/00000000-0000-0000-0000-000000000000"
41+
}
42+
}

0 commit comments

Comments
 (0)