Skip to content

Commit

Permalink
Merge pull request #5932 from espoon-voltti/children-without-shift-ca…
Browse files Browse the repository at this point in the history
…re-absent-on-weekends

Näytetään päivälapset mobiilissa poissaolevina viikonloppuisin
  • Loading branch information
Joosakur authored Nov 12, 2024
2 parents ad7a255 + 221166e commit debd78f
Show file tree
Hide file tree
Showing 7 changed files with 94 additions and 19 deletions.
70 changes: 63 additions & 7 deletions frontend/src/e2e-test/specs/6_mobile/child-attendances.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,7 @@ let listPage: MobileListPage
let childPage: MobileChildPage
let childAttendancePage: ChildAttendancePage

let now = HelsinkiDateTime.of(2024, 5, 17, 13, 0, 0)
let today = now.toLocalDate()
const now = HelsinkiDateTime.of(2024, 5, 17, 13, 0, 0)

const group2 = {
id: uuidv4(),
Expand Down Expand Up @@ -84,7 +83,8 @@ beforeEach(async () => {
async function createPlacements(
childId: string,
groupId: string = testDaycareGroup.id,
placementType: PlacementType = 'DAYCARE'
placementType: PlacementType = 'DAYCARE',
today: LocalDate = now.toLocalDate()
) {
const daycarePlacementFixture = await Fixture.placement({
childId,
Expand Down Expand Up @@ -471,6 +471,7 @@ describe('Child mobile attendance list', () => {
startDate: LocalDate.of(2022, 1, 1)
}).save()

const today = now.toLocalDate()
const placement1StartDate = today.subMonths(5)
const placement1EndDate = today.subMonths(1)

Expand Down Expand Up @@ -527,12 +528,38 @@ describe('Child mobile attendance list', () => {

test('Term break child is shown in absent list', async () => {
// change mocked now to be during term break
now = HelsinkiDateTime.of(2024, 1, 1, 13, 0, 0)
today = now.toLocalDate()
await openPage({ mockedTime: now })
const testNow = HelsinkiDateTime.of(2024, 1, 1, 13, 0, 0)
await openPage({ mockedTime: testNow })

const child = testChild2.id
await createPlacements(child, testDaycareGroup.id, 'PRESCHOOL')
await createPlacements(
child,
testDaycareGroup.id,
'PRESCHOOL',
testNow.toLocalDate()
)

const mobileSignupUrl = await pairMobileDevice(testDaycare.id)
await page.goto(mobileSignupUrl)

await assertAttendanceCounts(0, 0, 0, 1, 1)
await listPage.absentChildrenTab.click()
await listPage.selectChild(child)
await childPage.termBreak.waitUntilVisible()
})

test('Non operational day child is shown in absent list', async () => {
// change mocked now to be during weekend
const testNow = HelsinkiDateTime.of(2024, 5, 18, 13, 0, 0)
await openPage({ mockedTime: testNow })

const child = testChild2.id
await createPlacements(
child,
testDaycareGroup.id,
'PRESCHOOL',
testNow.toLocalDate()
)

const mobileSignupUrl = await pairMobileDevice(testDaycare.id)
await page.goto(mobileSignupUrl)
Expand All @@ -542,6 +569,35 @@ describe('Child mobile attendance list', () => {
await listPage.selectChild(child)
await childPage.termBreak.waitUntilVisible()
})

test('Child with shift care is shown in coming list even on weekend', async () => {
// change mocked now to be during weekend
const testNow = HelsinkiDateTime.of(2024, 5, 18, 13, 0, 0)
await openPage({ mockedTime: testNow })

const child = testChild2.id
const placement = await createPlacements(
child,
testDaycareGroup.id,
'PRESCHOOL',
testNow.toLocalDate()
)
const employee = await Fixture.employee().save()
const serviceNeedOption = await Fixture.serviceNeedOption().save()
await Fixture.serviceNeed({
placementId: placement.id,
startDate: placement.startDate,
endDate: placement.endDate,
shiftCare: 'FULL',
optionId: serviceNeedOption.id,
confirmedBy: employee.id
}).save()

const mobileSignupUrl = await pairMobileDevice(testDaycare.id)
await page.goto(mobileSignupUrl)

await assertAttendanceCounts(1, 0, 0, 0, 1)
})
})

describe('Notes on child departure page', () => {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/e2e-test/specs/6_mobile/messages.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ const staff2Name = `${staff2LastName} ${staff2FirstName}`

const pin = '2580'

const mockedDate = LocalDate.of(2022, 5, 21)
const mockedDate = LocalDate.of(2022, 5, 20) // Friday
const mockedDateAt10 = HelsinkiDateTime.fromLocal(
mockedDate,
LocalTime.of(10, 2)
Expand Down
27 changes: 18 additions & 9 deletions frontend/src/employee-mobile-frontend/child-attendance/utils.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2017-2022 City of Espoo
// SPDX-FileCopyrightText: 2017-2024 City of Espoo
//
// SPDX-License-Identifier: LGPL-2.1-or-later

Expand Down Expand Up @@ -31,28 +31,37 @@ export type AttendanceStatuses = Record<
ChildAttendanceStatusResponse | undefined
>

export type ChildAttendanceStatus = ChildAttendanceStatusResponse & {
hasOperationalDay: boolean
}

export function childAttendanceStatus(
child: AttendanceChild,
attendanceStatuses: Record<UUID, ChildAttendanceStatusResponse | undefined>
): ChildAttendanceStatusResponse {
): ChildAttendanceStatus {
const status = attendanceStatuses[child.id]
if (status) return status
if (status) return { ...status, hasOperationalDay: true }

if (child.scheduleType === 'TERM_BREAK') {
return defaultChildAttendanceStatusTermBreak
if (
child.scheduleType === 'TERM_BREAK' ||
!child.operationalDates.some((date) => date.isToday())
) {
return childAttendanceStatusNoService
}

return defaultChildAttendanceStatus
}

const defaultChildAttendanceStatus: ChildAttendanceStatusResponse = {
const defaultChildAttendanceStatus: ChildAttendanceStatus = {
status: 'COMING',
attendances: [],
absences: []
absences: [],
hasOperationalDay: true
}

const defaultChildAttendanceStatusTermBreak: ChildAttendanceStatusResponse = {
const childAttendanceStatusNoService: ChildAttendanceStatus = {
status: 'ABSENT',
attendances: [],
absences: []
absences: [],
hasOperationalDay: false
}
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ export default React.memo(function AttendanceChildPage({
</Zindex>

<FlexColumn paddingHorizontal="s">
{child.scheduleType !== 'TERM_BREAK' ? (
{childAttendance.hasOperationalDay ? (
<>
<AttendanceDailyServiceTimes
dailyServiceTimes={child.dailyServiceTimes}
Expand Down Expand Up @@ -246,7 +246,7 @@ export default React.memo(function AttendanceChildPage({
<AttendanceChildDeparted unitId={unitId} child={child} />
)}
{childAttendance.status === 'ABSENT' &&
child.scheduleType !== 'TERM_BREAK' && (
childAttendance.hasOperationalDay && (
<AttendanceChildAbsent
childId={childId}
unitId={unitId}
Expand Down
2 changes: 2 additions & 0 deletions frontend/src/lib-common/generated/api-types/attendance.ts
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@ export interface AttendanceChild {
id: UUID
imageUrl: string | null
lastName: string
operationalDates: LocalDate[]
placementType: PlacementType
preferredName: string
reservations: ReservationResponse[]
Expand Down Expand Up @@ -466,6 +467,7 @@ export function deserializeJsonAttendanceChild(json: JsonOf<AttendanceChild>): A
dailyNote: (json.dailyNote != null) ? deserializeJsonChildDailyNote(json.dailyNote) : null,
dailyServiceTimes: (json.dailyServiceTimes != null) ? deserializeJsonDailyServiceTimesValue(json.dailyServiceTimes) : null,
dateOfBirth: LocalDate.parseIso(json.dateOfBirth),
operationalDates: json.operationalDates.map(e => LocalDate.parseIso(e)),
reservations: json.reservations.map(e => deserializeJsonReservationResponse(e)),
stickyNotes: json.stickyNotes.map(e => deserializeJsonChildStickyNote(e))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ data class AttendanceChild(
val dateOfBirth: LocalDate,
val placementType: PlacementType,
val scheduleType: ScheduleType,
val operationalDates: Set<LocalDate>,
val groupId: GroupId?,
val backup: Boolean,
val dailyServiceTimes: DailyServiceTimesValue?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ import fi.espoo.evaka.shared.domain.EvakaClock
import fi.espoo.evaka.shared.domain.FiniteDateRange
import fi.espoo.evaka.shared.domain.HelsinkiDateTime
import fi.espoo.evaka.shared.domain.TimeInterval
import fi.espoo.evaka.shared.domain.getOperationalDatesForChildren
import fi.espoo.evaka.shared.security.AccessControl
import fi.espoo.evaka.shared.security.Action
import fi.espoo.evaka.shared.utils.mapOfNotNullValues
Expand Down Expand Up @@ -77,6 +78,11 @@ class ChildAttendanceController(

val childrenBasics = tx.fetchChildrenBasics(unitId, now)
val childIds = childrenBasics.asSequence().map { it.id }.toSet()
val operationalDatesByChild =
tx.getOperationalDatesForChildren(
range = FiniteDateRange(today, today.plusDays(7)),
children = childIds,
)

val dailyNotes =
tx.getChildDailyNotesForChildren(childIds).associateBy { it.childId }
Expand All @@ -94,6 +100,7 @@ class ChildAttendanceController(
placementType = child.placementType,
scheduleType =
child.placementType.scheduleType(today, clubTerms, preschoolTerms),
operationalDates = operationalDatesByChild[child.id] ?: emptySet(),
groupId = child.groupId,
backup = child.backup,
dailyServiceTimes = child.dailyServiceTimes?.times,
Expand Down

0 comments on commit debd78f

Please sign in to comment.