Skip to content

Commit b6a33a5

Browse files
authored
Merge pull request #6493 from espoon-voltti/linkity-enable-for-units
Toimintojen avauksien huomioiminen Linkity-integraatiossa
2 parents d28987b + 63d3eb2 commit b6a33a5

File tree

3 files changed

+114
-28
lines changed

3 files changed

+114
-28
lines changed

service/src/integrationTest/kotlin/fi/espoo/evaka/linkity/LinkityServiceTest.kt

+78-22
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,46 @@ package fi.espoo.evaka.linkity
77
import fi.espoo.evaka.FullApplicationTest
88
import fi.espoo.evaka.attendance.*
99
import fi.espoo.evaka.shared.GroupId
10+
import fi.espoo.evaka.shared.auth.UserRole
11+
import fi.espoo.evaka.shared.auth.insertDaycareAclRow
1012
import fi.espoo.evaka.shared.db.Database
1113
import fi.espoo.evaka.shared.dev.*
1214
import fi.espoo.evaka.shared.domain.FiniteDateRange
1315
import fi.espoo.evaka.shared.domain.HelsinkiDateTime
16+
import fi.espoo.evaka.shared.security.PilotFeature
1417
import java.time.LocalDate
1518
import kotlin.test.assertEquals
1619
import kotlin.test.assertTrue
20+
import org.junit.jupiter.api.BeforeEach
1721
import org.junit.jupiter.api.Test
1822

1923
internal class LinkityServiceTest : FullApplicationTest(resetDbBeforeEach = true) {
24+
val employeeNumber = "SARASTIA_1"
25+
lateinit var employee: DevEmployee
26+
lateinit var area: DevCareArea
27+
lateinit var daycare: DevDaycare
28+
29+
@BeforeEach
30+
fun beforeEach() {
31+
employee = DevEmployee(employeeNumber = employeeNumber)
32+
area = DevCareArea()
33+
daycare =
34+
DevDaycare(
35+
areaId = area.id,
36+
enabledPilotFeatures = setOf(PilotFeature.STAFF_ATTENDANCE_INTEGRATION),
37+
)
38+
db.transaction { tx ->
39+
tx.insert(area)
40+
tx.insert(daycare)
41+
tx.insert(employee)
42+
tx.insertDaycareAclRow(daycare.id, employee.id, UserRole.STAFF)
43+
}
44+
}
45+
2046
@Test
2147
fun `new plans from Linkity replace old plans`() {
2248
val today = LocalDate.now()
23-
val employeeNumber = "SARASTIA_1"
24-
val employee = DevEmployee(employeeNumber = employeeNumber)
2549
db.transaction { tx ->
26-
tx.insert(employee)
2750
tx.insertStaffAttendancePlans(
2851
sequenceOf(-1, 0, 1, 2)
2952
.map { days ->
@@ -67,9 +90,6 @@ internal class LinkityServiceTest : FullApplicationTest(resetDbBeforeEach = true
6790
@Test
6891
fun `new plans with unknown sarastia id are ignored`() {
6992
val today = LocalDate.now()
70-
val employeeNumber = "SARASTIA_2"
71-
val employee = DevEmployee(employeeNumber = employeeNumber)
72-
db.transaction { tx -> tx.insert(employee) }
7393
val period = FiniteDateRange(today, today.plusDays(1))
7494
val shifts =
7595
listOf(
@@ -93,9 +113,6 @@ internal class LinkityServiceTest : FullApplicationTest(resetDbBeforeEach = true
93113
@Test
94114
fun `new plans with invalid times are ignored`() {
95115
val today = LocalDate.now()
96-
val employeeNumber = "SARASTIA_3"
97-
val employee = DevEmployee(employeeNumber = employeeNumber)
98-
db.transaction { tx -> tx.insert(employee) }
99116
val period = FiniteDateRange(today, today.plusDays(1))
100117
val shifts =
101118
listOf(
@@ -119,9 +136,6 @@ internal class LinkityServiceTest : FullApplicationTest(resetDbBeforeEach = true
119136
@Test
120137
fun `new plans with overlapping times are ignored`() {
121138
val today = LocalDate.now()
122-
val employeeNumber = "SARASTIA_4"
123-
val employee = DevEmployee(employeeNumber = employeeNumber)
124-
db.transaction { tx -> tx.insert(employee) }
125139
val period = FiniteDateRange(today, today.plusDays(1))
126140
val shifts =
127141
listOf(
@@ -151,6 +165,37 @@ internal class LinkityServiceTest : FullApplicationTest(resetDbBeforeEach = true
151165
assertTrue { plans.any { it.description == "Uusi" && it.startTime.hour == 8 } }
152166
}
153167

168+
@Test
169+
fun `new plans for employees in disabled daycares are ignored`() {
170+
val today = LocalDate.now()
171+
val employeeNumber2 = "SARASTIA_2"
172+
val employee2 = DevEmployee(employeeNumber = employeeNumber2)
173+
val daycare2 = DevDaycare(areaId = area.id, enabledPilotFeatures = setOf())
174+
db.transaction { tx ->
175+
tx.insert(daycare2)
176+
tx.insert(employee2)
177+
tx.insertDaycareAclRow(daycare2.id, employee2.id, UserRole.STAFF)
178+
}
179+
val period = FiniteDateRange(today, today.plusDays(1))
180+
val shifts =
181+
listOf(
182+
Shift(
183+
employeeNumber2,
184+
"WORK_SHIFT_1",
185+
HelsinkiDateTime.of(today.atTime(8, 0)),
186+
HelsinkiDateTime.of(today.atTime(16, 0)),
187+
ShiftType.PRESENT,
188+
"Uusi",
189+
)
190+
)
191+
val client = MockLinkityClient(shifts)
192+
updateStaffAttendancePlansFromLinkity(period, db, client)
193+
194+
val plans = db.transaction { tx -> tx.findStaffAttendancePlansBy() }
195+
// There will be no plans
196+
assertEquals(0, plans.size)
197+
}
198+
154199
private fun upsertStaffAttendance(
155200
tx: Database.Transaction,
156201
employee: DevEmployee,
@@ -176,18 +221,19 @@ internal class LinkityServiceTest : FullApplicationTest(resetDbBeforeEach = true
176221
@Test
177222
fun `relevant attendances are sent to Linkity`() {
178223
val now = HelsinkiDateTime.now()
179-
val employeeNumber = "SARASTIA_1"
180224
db.transaction { tx ->
181-
val area = DevCareArea()
182-
val unit = DevDaycare(areaId = area.id)
183-
val group = DevDaycareGroup(daycareId = unit.id)
184-
val employee = DevEmployee(employeeNumber = employeeNumber)
185-
val employee2 = DevEmployee(employeeNumber = null)
186-
tx.insert(area)
187-
tx.insert(unit)
225+
val group = DevDaycareGroup(daycareId = daycare.id)
226+
val employee2 = DevEmployee(employeeNumber = "SARASTIA_2")
227+
val employee3 = DevEmployee(employeeNumber = null)
228+
val daycare2 = DevDaycare(areaId = area.id, enabledPilotFeatures = setOf())
229+
val group2 = DevDaycareGroup(daycareId = daycare2.id)
230+
tx.insert(daycare2)
188231
tx.insert(group)
189-
tx.insert(employee)
232+
tx.insert(group2)
190233
tx.insert(employee2)
234+
tx.insert(employee3)
235+
tx.insertDaycareAclRow(daycare2.id, employee2.id, UserRole.STAFF)
236+
tx.insertDaycareAclRow(daycare.id, employee3.id, UserRole.STAFF)
191237
tx.insertStaffAttendancePlans(
192238
listOf(
193239
StaffAttendancePlan(
@@ -270,12 +316,21 @@ internal class LinkityServiceTest : FullApplicationTest(resetDbBeforeEach = true
270316
// 7th
271317
upsertStaffAttendance(
272318
tx,
273-
employee2,
319+
employee3,
274320
group.id,
275321
now.minusHours(4),
276322
now.minusHours(3),
277323
StaffAttendanceType.PRESENT,
278324
)
325+
// 8th
326+
upsertStaffAttendance(
327+
tx,
328+
employee2,
329+
group2.id,
330+
now.minusHours(5),
331+
now.minusHours(4),
332+
StaffAttendanceType.PRESENT,
333+
)
279334
}
280335
val period = FiniteDateRange(now.minusDays(1).toLocalDate(), now.toLocalDate())
281336

@@ -316,6 +371,7 @@ internal class LinkityServiceTest : FullApplicationTest(resetDbBeforeEach = true
316371
),
317372
// 6th attendance is not included because it has not ended yet
318373
// 7th attendance is not included because the employee has no employee number
374+
// 8th attendance is not included because the employee is not in an enabled daycare
319375
)
320376

321377
assertEquals(expected, client.getPreviouslyPostedWorkLogs().toSet())

service/src/main/kotlin/fi/espoo/evaka/linkity/LinkityQueries.kt

+33-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,9 @@ data class ExportableAttendance(
1818
val sarastiaId: String,
1919
)
2020

21-
fun Database.Read.getStaffAttendances(range: FiniteDateRange): List<ExportableAttendance> {
21+
fun Database.Read.getStaffAttendancesForEnabledDaycares(
22+
range: FiniteDateRange
23+
): List<ExportableAttendance> {
2224
return createQuery {
2325
sql(
2426
"""
@@ -30,9 +32,38 @@ SELECT
3032
emp.employee_number as sarastia_id
3133
FROM staff_attendance_realtime sa
3234
JOIN employee emp ON sa.employee_id = emp.id
33-
WHERE emp.employee_number IS NOT NULL AND ${bind(range.asHelsinkiDateTimeRange())} @> arrived and departed IS NOT NULL
35+
WHERE emp.employee_number IS NOT NULL
36+
AND ${bind(range.asHelsinkiDateTimeRange())} @> arrived
37+
AND departed IS NOT NULL
38+
AND EXISTS (
39+
SELECT
40+
FROM daycare_acl acl
41+
JOIN daycare d ON acl.daycare_id = d.id
42+
WHERE acl.employee_id = emp.id AND 'STAFF_ATTENDANCE_INTEGRATION' = ANY(d.enabled_pilot_features)
43+
)
3444
"""
3545
)
3646
}
3747
.toList()
3848
}
49+
50+
fun Database.Read.getEmployeeIdsForEnabledDaycares(
51+
employeeNumbers: Collection<String>
52+
): Map<String, EmployeeId> {
53+
return createQuery {
54+
sql(
55+
"""
56+
SELECT id, employee_number
57+
FROM employee e
58+
WHERE employee_number = ANY (${bind(employeeNumbers)})
59+
AND EXISTS (
60+
SELECT
61+
FROM daycare_acl acl
62+
JOIN daycare d ON acl.daycare_id = d.id
63+
WHERE acl.employee_id = e.id AND 'STAFF_ATTENDANCE_INTEGRATION' = ANY(d.enabled_pilot_features)
64+
)
65+
"""
66+
)
67+
}
68+
.toMap { columnPair("employee_number", "id") }
69+
}

service/src/main/kotlin/fi/espoo/evaka/linkity/LinkityService.kt

+3-4
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import com.fasterxml.jackson.databind.json.JsonMapper
88
import fi.espoo.evaka.LinkityEnv
99
import fi.espoo.evaka.attendance.*
1010
import fi.espoo.evaka.espoo.EspooAsyncJob
11-
import fi.espoo.evaka.pis.getEmployeeIdsByNumbers
1211
import fi.espoo.evaka.shared.EmployeeId
1312
import fi.espoo.evaka.shared.db.Database
1413
import fi.espoo.evaka.shared.domain.EvakaClock
@@ -58,7 +57,7 @@ fun updateStaffAttendancePlansFromLinkity(
5857
val sarastiaIds = linkityShifts.map { it.sarastiaId }.toSet()
5958

6059
db.transaction { tx ->
61-
val sarastiaIdToEmployeeId = tx.getEmployeeIdsByNumbers(sarastiaIds)
60+
val sarastiaIdToEmployeeId = tx.getEmployeeIdsForEnabledDaycares(sarastiaIds)
6261

6362
val shifts = filterValidShifts(linkityShifts, sarastiaIdToEmployeeId)
6463

@@ -93,7 +92,7 @@ private fun filterValidShifts(
9392
shifts.partition { sarastiaIdToEmployeeId.containsKey(it.sarastiaId) }
9493
if (withUnknownSarastiaId.isNotEmpty()) {
9594
logger.info {
96-
"No employee found for Sarastia IDs: ${withUnknownSarastiaId.map { it.sarastiaId }}"
95+
"No employee found from any enabled daycare for Sarastia IDs: ${withUnknownSarastiaId.map { it.sarastiaId }}"
9796
}
9897
}
9998
val (validTimesShifts, invalidTimesShifts) =
@@ -124,7 +123,7 @@ fun sendStaffAttendancesToLinkity(
124123
lateinit var plans: Map<EmployeeId, List<StaffAttendancePlan>>
125124

126125
db.transaction { tx ->
127-
attendances = tx.getStaffAttendances(period).groupBy { it.employeeId }
126+
attendances = tx.getStaffAttendancesForEnabledDaycares(period).groupBy { it.employeeId }
128127
val employeeIds = attendances.keys
129128
plans =
130129
tx.findStaffAttendancePlansBy(period = period, employeeIds = employeeIds).groupBy {

0 commit comments

Comments
 (0)