Skip to content

Commit

Permalink
Add out of office update endpoint
Browse files Browse the repository at this point in the history
  • Loading branch information
terolaakso committed Dec 27, 2024
1 parent 72e20b2 commit d0d7d73
Show file tree
Hide file tree
Showing 5 changed files with 102 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import fi.espoo.evaka.shared.dev.DevCareArea
import fi.espoo.evaka.shared.dev.DevDaycare
import fi.espoo.evaka.shared.dev.DevEmployee
import fi.espoo.evaka.shared.dev.insert
import fi.espoo.evaka.shared.domain.FiniteDateRange
import fi.espoo.evaka.shared.domain.RealEvakaClock
import java.util.*
import kotlin.test.Test
Expand Down Expand Up @@ -44,8 +45,36 @@ class OutOfOfficeIntegrationTest : FullApplicationTest(resetDbBeforeEach = true)
}

@Test
fun `get out of office periods`() {
val ranges = outOfOfficeController.getOutOfOfficePeriods(dbInstance(), employee, clock)
assertEquals(0, ranges.size)
fun `out of office periods`() {
val initialPeriods =
outOfOfficeController.getOutOfOfficePeriods(dbInstance(), employee, clock)
assertEquals(0, initialPeriods.size)

val period =
OutOfOfficePeriodUpsert(
id = null,
period =
FiniteDateRange(
start = clock.today().plusDays(1),
end = clock.today().plusDays(2),
),
)
outOfOfficeController.upsertOutOfOfficePeriod(dbInstance(), employee, clock, period)
val addedPeriod = outOfOfficeController.getOutOfOfficePeriods(dbInstance(), employee, clock)
assertEquals(listOf(period.period), addedPeriod.map { it.period })

val updatedPeriod =
OutOfOfficePeriodUpsert(
id = addedPeriod.first().id,
period =
FiniteDateRange(
start = clock.today().plusDays(3),
end = clock.today().plusDays(4),
),
)
outOfOfficeController.upsertOutOfOfficePeriod(dbInstance(), employee, clock, updatedPeriod)
val updatedPeriods =
outOfOfficeController.getOutOfOfficePeriods(dbInstance(), employee, clock)
assertEquals(listOf(updatedPeriod.period), updatedPeriods.map { it.period })
}
}
1 change: 1 addition & 0 deletions service/src/main/kotlin/fi/espoo/evaka/Audit.kt
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,7 @@ enum class Audit(
OtherAssistanceMeasureUpdate,
OtherAssistanceMeasureDelete,
OutOfOfficeRead,
OutOfOfficeUpdate,
PairingInit(securityEvent = true),
PairingChallenge(securityEvent = true),
PairingResponse(securityEvent = true, securityLevel = "high"),
Expand Down
44 changes: 38 additions & 6 deletions service/src/main/kotlin/fi/espoo/evaka/outofoffice/OutOfOffice.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,51 @@ import java.time.LocalDate

data class OutOfOfficePeriod(val id: OutOfOfficeId, val period: FiniteDateRange)

data class OutOfOfficePeriodUpsert(val id: OutOfOfficeId?, val period: FiniteDateRange)

fun Database.Read.getOutOfOfficePeriods(
employeeId: EmployeeId,
today: LocalDate,
): List<OutOfOfficePeriod> {
return createQuery {
sql(
"""
val result =
createQuery {
sql(
"""
SELECT id, daterange(start_date, end_date, '[]') AS period
FROM out_of_office
WHERE employee_id = ${bind(employeeId)}
AND end_date >= ${bind(today)}
"""
)
}
.toList<OutOfOfficePeriod>()
)
}
.toList<OutOfOfficePeriod>()
return result
}

fun Database.Transaction.upsertOutOfOfficePeriod(
employeeId: EmployeeId,
period: OutOfOfficePeriodUpsert,
) {
if (period.id == null) {
createUpdate {
sql(
"""
INSERT INTO out_of_office (employee_id, start_date, end_date)
VALUES (${bind(employeeId)}, ${bind(period.period.start)}, ${bind(period.period.end)})
"""
)
}
.execute()
} else {
createUpdate {
sql(
"""
UPDATE out_of_office
SET start_date = ${bind(period.period.start)}, end_date = ${bind(period.period.end)}
WHERE id = ${bind(period.id)}
"""
)
}
.updateExactlyOne()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package fi.espoo.evaka.outofoffice
import fi.espoo.evaka.Audit
import fi.espoo.evaka.shared.auth.AuthenticatedUser
import fi.espoo.evaka.shared.db.Database
import fi.espoo.evaka.shared.domain.BadRequest
import fi.espoo.evaka.shared.domain.EvakaClock
import fi.espoo.evaka.shared.security.AccessControl
import fi.espoo.evaka.shared.security.Action
import org.springframework.web.bind.annotation.GetMapping
import org.springframework.web.bind.annotation.PostMapping
import org.springframework.web.bind.annotation.RestController

@RestController
Expand All @@ -32,4 +34,32 @@ class OutOfOfficeController(private val accessControl: AccessControl) {
}
.also { Audit.OutOfOfficeRead.log(targetId = fi.espoo.evaka.AuditId(user.id)) }
}

@PostMapping("/employee/out-of-office")
fun upsertOutOfOfficePeriod(
db: Database,
user: AuthenticatedUser.Employee,
clock: EvakaClock,
body: OutOfOfficePeriodUpsert,
) {
return db.connect { dbc ->
dbc.transaction {
accessControl.requirePermissionFor(
it,
user,
clock,
Action.Employee.UPDATE_OUT_OF_OFFICE,
user.id,
)
if (body.period.start.isBefore(clock.today())) {
throw BadRequest("Cannot create out-of-office period in the past")
}
if (body.period.start.isAfter(body.period.end)) {
throw BadRequest("Start date must be before end date")
}
it.upsertOutOfOfficePeriod(employeeId = user.id, period = body)
}
}
.also { Audit.OutOfOfficeUpdate.log(targetId = fi.espoo.evaka.AuditId(user.id)) }
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
CREATE TABLE out_of_office
(
id UUID PRIMARY KEY,
id UUID PRIMARY KEY DEFAULT ext.uuid_generate_v1mc(),
employee_id UUID NOT NULL,
start_date DATE NOT NULL,
end_date DATE NOT NULL
Expand Down

0 comments on commit d0d7d73

Please sign in to comment.