Skip to content

Commit eb08419

Browse files
Merge pull request #6316 from espoon-voltti/finance-note
Talouden muistiinpano aikuisen tietoihin
2 parents c44c724 + 30ed3dc commit eb08419

File tree

24 files changed

+896
-1
lines changed

24 files changed

+896
-1
lines changed

frontend/src/e2e-test/generated/api-clients.ts

+24
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ import { DevDocumentTemplate } from './api-types'
5959
import { DevEmployee } from './api-types'
6060
import { DevEmployeePin } from './api-types'
6161
import { DevFamilyContact } from './api-types'
62+
import { DevFinanceNote } from './api-types'
6263
import { DevFosterParent } from './api-types'
6364
import { DevFridgeChild } from './api-types'
6465
import { DevFridgePartner } from './api-types'
@@ -1091,6 +1092,29 @@ export async function createFeeThresholds(
10911092
}
10921093

10931094

1095+
/**
1096+
* Generated from fi.espoo.evaka.shared.dev.DevApi.createFinanceNotes
1097+
*/
1098+
export async function createFinanceNotes(
1099+
request: {
1100+
body: DevFinanceNote[]
1101+
},
1102+
options?: { mockedTime?: HelsinkiDateTime }
1103+
): Promise<void> {
1104+
try {
1105+
const { data: json } = await devClient.request<JsonOf<void>>({
1106+
url: uri`/finance-notes`.toString(),
1107+
method: 'POST',
1108+
headers: { EvakaMockedTime: options?.mockedTime?.formatIso() },
1109+
data: request.body satisfies JsonCompatible<DevFinanceNote[]>
1110+
})
1111+
return json
1112+
} catch (e) {
1113+
throw new DevApiError(e)
1114+
}
1115+
}
1116+
1117+
10941118
/**
10951119
* Generated from fi.espoo.evaka.shared.dev.DevApi.createFosterParent
10961120
*/

frontend/src/e2e-test/generated/api-types.ts

+8
Original file line numberDiff line numberDiff line change
@@ -614,6 +614,14 @@ export interface DevFamilyContact {
614614
priority: number
615615
}
616616

617+
/**
618+
* Generated from fi.espoo.evaka.shared.dev.DevApi.DevFinanceNote
619+
*/
620+
export interface DevFinanceNote {
621+
content: string
622+
personId: PersonId
623+
}
624+
617625
/**
618626
* Generated from fi.espoo.evaka.shared.dev.DevFosterParent
619627
*/

frontend/src/e2e-test/pages/employee/guardian-information.ts

+15
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
//
33
// SPDX-License-Identifier: LGPL-2.1-or-later
44

5+
import HelsinkiDateTime from 'lib-common/helsinki-date-time'
56
import LocalDate from 'lib-common/local-date'
67
import { formatCents } from 'lib-common/money'
78
import { UUID } from 'lib-common/types'
@@ -655,6 +656,16 @@ class InvoiceCorrectionNoteModal extends Modal {
655656
note = new TextInput(this.findByDataQa('note-textarea'))
656657
}
657658

659+
class FinanceNotesAndMessagesSection extends Section {
660+
#noteCreatedAt = this.findAll(`[data-qa="finance-note-created-at"]`)
661+
662+
async checkNoteCreatedAt(nth: number, expectedCreatedAt: HelsinkiDateTime) {
663+
await this.#noteCreatedAt
664+
.nth(nth)
665+
.assertTextEquals(expectedCreatedAt.format())
666+
}
667+
}
668+
658669
const collapsibles = {
659670
personInfo: {
660671
selector: '[data-qa="person-info-collapsible"]',
@@ -707,6 +718,10 @@ const collapsibles = {
707718
invoiceCorrections: {
708719
selector: '[data-qa="person-invoice-corrections-collapsible"]',
709720
section: InvoiceCorrectionsSection
721+
},
722+
financeNotesAndMessages: {
723+
selector: '[data-qa="person-finance-notes-and-messages-collapsible"]',
724+
section: FinanceNotesAndMessagesSection
710725
}
711726
}
712727

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
// SPDX-FileCopyrightText: 2017-2025 City of Espoo
2+
//
3+
// SPDX-License-Identifier: LGPL-2.1-or-later
4+
5+
import HelsinkiDateTime from 'lib-common/helsinki-date-time'
6+
7+
import config from '../../config'
8+
import { Fixture, testAdult } from '../../dev-api/fixtures'
9+
import {
10+
createFinanceNotes,
11+
resetServiceState
12+
} from '../../generated/api-clients'
13+
import GuardianInformationPage from '../../pages/employee/guardian-information'
14+
import { Page } from '../../utils/page'
15+
import { employeeLogin } from '../../utils/user'
16+
17+
let page: Page
18+
let guardianPage: GuardianInformationPage
19+
20+
beforeEach(async () => {
21+
await resetServiceState()
22+
await Fixture.person(testAdult).saveAdult()
23+
const financeAdmin = await Fixture.employee().financeAdmin().save()
24+
25+
page = await Page.open({})
26+
await employeeLogin(page, financeAdmin)
27+
28+
await page.goto(config.employeeUrl)
29+
guardianPage = new GuardianInformationPage(page)
30+
})
31+
32+
describe('person finance notes', () => {
33+
test('Notes are sorted by created date', async () => {
34+
const createdAtFirst = HelsinkiDateTime.now().subHours(3 * 24)
35+
const createdAtSecond = createdAtFirst.addHours(24)
36+
const createdAtThird = createdAtSecond.addHours(24)
37+
38+
const createFinanceNoteFixture = async (createdAt: HelsinkiDateTime) => {
39+
await createFinanceNotes(
40+
{
41+
body: [{ personId: testAdult.id, content: 'foobar' }]
42+
},
43+
{
44+
mockedTime: createdAt
45+
}
46+
)
47+
}
48+
49+
await createFinanceNoteFixture(createdAtFirst)
50+
await createFinanceNoteFixture(createdAtSecond)
51+
await createFinanceNoteFixture(createdAtThird)
52+
53+
await guardianPage.navigateToGuardian(testAdult.id)
54+
const notes = await guardianPage.openCollapsible('financeNotesAndMessages')
55+
56+
await notes.checkNoteCreatedAt(0, createdAtThird)
57+
await notes.checkNoteCreatedAt(1, createdAtSecond)
58+
await notes.checkNoteCreatedAt(2, createdAtFirst)
59+
})
60+
})

frontend/src/employee-frontend/components/PersonProfile.tsx

+9-1
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,7 @@ import { UserContext } from '../state/user'
4343
import { getLayout, Layouts } from './layouts'
4444
import FosterChildren from './person-profile/FosterChildren'
4545
import FamilyOverview from './person-profile/PersonFamilyOverview'
46+
import PersonFinanceNotesAndMessages from './person-profile/PersonFinanceNotesAndMessages'
4647
import PersonInvoiceCorrections from './person-profile/PersonInvoiceCorrections'
4748
import PersonVoucherValueDecisions from './person-profile/PersonVoucherValueDecisions'
4849

@@ -135,11 +136,16 @@ const components = {
135136
PersonApplications,
136137
'READ_APPLICATIONS'
137138
),
138-
decisions: requireOneOfPermittedActions(PersonDecisions, 'READ_DECISIONS')
139+
decisions: requireOneOfPermittedActions(PersonDecisions, 'READ_DECISIONS'),
140+
'notes-and-messages': requireOneOfPermittedActions(
141+
PersonFinanceNotesAndMessages,
142+
'READ_FINANCE_NOTES'
143+
)
139144
}
140145

141146
const layouts: Layouts<typeof components> = {
142147
['ADMIN']: [
148+
{ component: 'notes-and-messages', open: true },
143149
{ component: 'family-overview', open: true },
144150
{ component: 'partners', open: false },
145151
{ component: 'fridge-children', open: false },
@@ -168,6 +174,7 @@ const layouts: Layouts<typeof components> = {
168174
{ component: 'voucherValueDecisions', open: false }
169175
],
170176
['FINANCE_ADMIN']: [
177+
{ component: 'notes-and-messages', open: true },
171178
{ component: 'family-overview', open: true },
172179
{ component: 'income', open: true },
173180
{ component: 'fee-decisions', open: false },
@@ -180,6 +187,7 @@ const layouts: Layouts<typeof components> = {
180187
{ component: 'fosterChildren', open: false }
181188
],
182189
['FINANCE_STAFF']: [
190+
{ component: 'notes-and-messages', open: true },
183191
{ component: 'family-overview', open: true },
184192
{ component: 'fee-decisions', open: false },
185193
{ component: 'invoices', open: false },

0 commit comments

Comments
 (0)