diff --git a/frontend/src/citizen-frontend/applications/editor/verification/BasicsSection.tsx b/frontend/src/citizen-frontend/applications/editor/verification/BasicsSection.tsx
index 6f37f3d5ed1..fd89d0d6613 100644
--- a/frontend/src/citizen-frontend/applications/editor/verification/BasicsSection.tsx
+++ b/frontend/src/citizen-frontend/applications/editor/verification/BasicsSection.tsx
@@ -24,8 +24,8 @@ export default React.memo(function BasicsSection({
}: BasicsSectionProps) {
const t = useTranslation()
- const created = application.createdDate?.toLocalDate()
- const modified = application.modifiedDate?.toLocalDate()
+ const created = application.createdAt?.toLocalDate()
+ const modified = application.modifiedAt?.toLocalDate()
return (
diff --git a/frontend/src/e2e-test/dev-api/fixtures.ts b/frontend/src/e2e-test/dev-api/fixtures.ts
index ffcc90f72e5..a3f0b075565 100644
--- a/frontend/src/e2e-test/dev-api/fixtures.ts
+++ b/frontend/src/e2e-test/dev-api/fixtures.ts
@@ -2950,11 +2950,12 @@ export const applicationFixture = (
status,
transferApplication,
allowOtherGuardianAccess: true,
- createdDate: null,
+ createdAt: HelsinkiDateTime.now(),
+ createdBy: systemInternalUser.id,
+ modifiedAt: HelsinkiDateTime.now(),
+ modifiedBy: systemInternalUser.id,
dueDate: null,
- modifiedDate: null,
- sentDate: null,
- formModified: HelsinkiDateTime.now()
+ sentDate: null
})
const feeThresholds = {
diff --git a/frontend/src/e2e-test/generated/api-types.ts b/frontend/src/e2e-test/generated/api-types.ts
index b4911ac487d..97d0428ed31 100644
--- a/frontend/src/e2e-test/generated/api-types.ts
+++ b/frontend/src/e2e-test/generated/api-types.ts
@@ -199,14 +199,15 @@ export interface DevApplicationWithForm {
checkedByAdmin: boolean
childId: PersonId
confidential: boolean | null
- createdDate: HelsinkiDateTime | null
+ createdAt: HelsinkiDateTime
+ createdBy: EvakaUserId
dueDate: LocalDate | null
form: ApplicationForm
- formModified: HelsinkiDateTime
guardianId: PersonId
hideFromGuardian: boolean
id: ApplicationId
- modifiedDate: HelsinkiDateTime | null
+ modifiedAt: HelsinkiDateTime
+ modifiedBy: EvakaUserId
origin: ApplicationOrigin
otherGuardians: PersonId[]
sentDate: LocalDate | null
@@ -1180,11 +1181,10 @@ export function deserializeJsonDevAbsence(json: JsonOf
): DevAbsence
export function deserializeJsonDevApplicationWithForm(json: JsonOf): DevApplicationWithForm {
return {
...json,
- createdDate: (json.createdDate != null) ? HelsinkiDateTime.parseIso(json.createdDate) : null,
+ createdAt: HelsinkiDateTime.parseIso(json.createdAt),
dueDate: (json.dueDate != null) ? LocalDate.parseIso(json.dueDate) : null,
form: deserializeJsonApplicationForm(json.form),
- formModified: HelsinkiDateTime.parseIso(json.formModified),
- modifiedDate: (json.modifiedDate != null) ? HelsinkiDateTime.parseIso(json.modifiedDate) : null,
+ modifiedAt: HelsinkiDateTime.parseIso(json.modifiedAt),
sentDate: (json.sentDate != null) ? LocalDate.parseIso(json.sentDate) : null
}
}
diff --git a/frontend/src/employee-frontend/components/application-page/ApplicationStatusSection.tsx b/frontend/src/employee-frontend/components/application-page/ApplicationStatusSection.tsx
index 9af6a50b39a..5cde554fc3c 100755
--- a/frontend/src/employee-frontend/components/application-page/ApplicationStatusSection.tsx
+++ b/frontend/src/employee-frontend/components/application-page/ApplicationStatusSection.tsx
@@ -48,7 +48,12 @@ export default React.memo(function ApplicationStatusSection({
- {application.modifiedDate?.format() ?? ''}
+ {application.modifiedAt?.format() ?? ''}
+
+
+
+
+ {application.modifiedBy?.name ?? ''}
diff --git a/frontend/src/lib-common/generated/api-types/application.ts b/frontend/src/lib-common/generated/api-types/application.ts
index 683cd502712..d765792ebec 100644
--- a/frontend/src/lib-common/generated/api-types/application.ts
+++ b/frontend/src/lib-common/generated/api-types/application.ts
@@ -122,7 +122,8 @@ export interface ApplicationDetails {
childId: PersonId
childRestricted: boolean
confidential: boolean | null
- createdDate: HelsinkiDateTime | null
+ createdAt: HelsinkiDateTime | null
+ createdBy: EvakaUser | null
dueDate: LocalDate | null
dueDateSetManuallyAt: HelsinkiDateTime | null
form: ApplicationForm
@@ -132,7 +133,8 @@ export interface ApplicationDetails {
hasOtherGuardian: boolean
hideFromGuardian: boolean
id: ApplicationId
- modifiedDate: HelsinkiDateTime | null
+ modifiedAt: HelsinkiDateTime | null
+ modifiedBy: EvakaUser | null
origin: ApplicationOrigin
otherGuardianLivesInSameAddress: boolean | null
sentDate: LocalDate | null
@@ -831,12 +833,12 @@ export function deserializeJsonApplicationDetails(json: JsonOf deserializeJsonApplicationAttachment(e)),
- createdDate: (json.createdDate != null) ? HelsinkiDateTime.parseIso(json.createdDate) : null,
+ createdAt: (json.createdAt != null) ? HelsinkiDateTime.parseIso(json.createdAt) : null,
dueDate: (json.dueDate != null) ? LocalDate.parseIso(json.dueDate) : null,
dueDateSetManuallyAt: (json.dueDateSetManuallyAt != null) ? HelsinkiDateTime.parseIso(json.dueDateSetManuallyAt) : null,
form: deserializeJsonApplicationForm(json.form),
guardianDateOfDeath: (json.guardianDateOfDeath != null) ? LocalDate.parseIso(json.guardianDateOfDeath) : null,
- modifiedDate: (json.modifiedDate != null) ? HelsinkiDateTime.parseIso(json.modifiedDate) : null,
+ modifiedAt: (json.modifiedAt != null) ? HelsinkiDateTime.parseIso(json.modifiedAt) : null,
sentDate: (json.sentDate != null) ? LocalDate.parseIso(json.sentDate) : null
}
}
diff --git a/frontend/src/lib-customizations/defaults/employee/i18n/fi.tsx b/frontend/src/lib-customizations/defaults/employee/i18n/fi.tsx
index cbf0e711dce..037826b786b 100755
--- a/frontend/src/lib-customizations/defaults/employee/i18n/fi.tsx
+++ b/frontend/src/lib-customizations/defaults/employee/i18n/fi.tsx
@@ -579,6 +579,7 @@ export const fi = {
origin: 'Hakemuksen lähetysmuoto',
sent: 'Saapunut',
modified: 'Muokattu viimeksi',
+ modifiedBy: 'Muokkaaja',
due: 'Käsiteltävä viimeistään'
},
date: {
diff --git a/service/src/integrationTest/kotlin/fi/espoo/evaka/TestFixtures.kt b/service/src/integrationTest/kotlin/fi/espoo/evaka/TestFixtures.kt
index 619051f505d..70b76e01744 100755
--- a/service/src/integrationTest/kotlin/fi/espoo/evaka/TestFixtures.kt
+++ b/service/src/integrationTest/kotlin/fi/espoo/evaka/TestFixtures.kt
@@ -672,8 +672,10 @@ fun Database.Transaction.insertApplication(
guardianId = guardian.id,
guardianRestricted = false,
guardianDateOfDeath = null,
- createdDate = HelsinkiDateTime.now(),
- modifiedDate = HelsinkiDateTime.now(),
+ createdAt = HelsinkiDateTime.now(),
+ createdBy = testDecisionMaker_1.toEvakaUser(),
+ modifiedAt = HelsinkiDateTime.now(),
+ modifiedBy = testDecisionMaker_1.toEvakaUser(),
sentDate = null,
dueDate = null,
dueDateSetManuallyAt = null,
diff --git a/service/src/integrationTest/kotlin/fi/espoo/evaka/application/GetApplicationIntegrationTests.kt b/service/src/integrationTest/kotlin/fi/espoo/evaka/application/GetApplicationIntegrationTests.kt
index 9d0be6cb542..24fbd671e90 100755
--- a/service/src/integrationTest/kotlin/fi/espoo/evaka/application/GetApplicationIntegrationTests.kt
+++ b/service/src/integrationTest/kotlin/fi/espoo/evaka/application/GetApplicationIntegrationTests.kt
@@ -229,7 +229,7 @@ class GetApplicationIntegrationTests : FullApplicationTest(resetDbBeforeEach = t
db.transaction { tx ->
tx.execute {
sql(
- "UPDATE application SET created = '2020-01-01T00:00:00Z' WHERE id = ${bind(old)}"
+ "UPDATE application SET created_at = '2020-01-01T00:00:00Z' WHERE id = ${bind(old)}"
)
}
}
diff --git a/service/src/integrationTest/kotlin/fi/espoo/evaka/shared/db/SchemaConventionsTest.kt b/service/src/integrationTest/kotlin/fi/espoo/evaka/shared/db/SchemaConventionsTest.kt
index aa82affdf49..a6e99269471 100644
--- a/service/src/integrationTest/kotlin/fi/espoo/evaka/shared/db/SchemaConventionsTest.kt
+++ b/service/src/integrationTest/kotlin/fi/espoo/evaka/shared/db/SchemaConventionsTest.kt
@@ -29,7 +29,6 @@ class SchemaConventionsTest : PureJdbiTest(resetDbBeforeEach = false) {
fun `creation timestamp should be called 'created_at' instead of 'created'`() {
val permittedViolations =
setOf(
- "application",
"application_form",
"application_note",
"application_other_guardian",
@@ -125,7 +124,6 @@ class SchemaConventionsTest : PureJdbiTest(resetDbBeforeEach = false) {
fun `update timestamp should be called 'updated_at' instead of 'updated'`() {
val permittedViolations =
setOf(
- "application",
"application_form",
"application_note",
"application_other_guardian",
@@ -395,7 +393,6 @@ class SchemaConventionsTest : PureJdbiTest(resetDbBeforeEach = false) {
fun `'created_by' column should be 'uuid' and NOT NULL`() {
val permittedViolations =
setOf(
- Column(ColumnRef("application", "created_by"), "uuid", nullable = true),
Column(
ColumnRef("assistance_need_decision", "created_by"),
"uuid",
diff --git a/service/src/integrationTest/kotlin/fi/espoo/evaka/shared/job/ScheduledJobsTest.kt b/service/src/integrationTest/kotlin/fi/espoo/evaka/shared/job/ScheduledJobsTest.kt
index bf051fbb87d..e757be31243 100644
--- a/service/src/integrationTest/kotlin/fi/espoo/evaka/shared/job/ScheduledJobsTest.kt
+++ b/service/src/integrationTest/kotlin/fi/espoo/evaka/shared/job/ScheduledJobsTest.kt
@@ -121,7 +121,7 @@ class ScheduledJobsTest : FullApplicationTest(resetDbBeforeEach = true) {
) =
tx.execute {
sql(
- "UPDATE application SET created = ${bind(created)} WHERE id = ${bind(applicationId)}"
+ "UPDATE application SET created_at = ${bind(created)} WHERE id = ${bind(applicationId)}"
)
}
diff --git a/service/src/integrationTest/kotlin/fi/espoo/evaka/test/TestData.kt b/service/src/integrationTest/kotlin/fi/espoo/evaka/test/TestData.kt
index b41de83b4e2..2995046112d 100644
--- a/service/src/integrationTest/kotlin/fi/espoo/evaka/test/TestData.kt
+++ b/service/src/integrationTest/kotlin/fi/espoo/evaka/test/TestData.kt
@@ -23,6 +23,8 @@ import fi.espoo.evaka.shared.domain.HelsinkiDateTime
import fi.espoo.evaka.testAdult_1
import fi.espoo.evaka.testChild_1
import fi.espoo.evaka.testDaycare
+import fi.espoo.evaka.testDecisionMaker_1
+import fi.espoo.evaka.toEvakaUser
import java.time.LocalDate
import java.time.LocalTime
import java.util.UUID
@@ -50,8 +52,10 @@ private fun applicationDetails(vararg preferredUnits: PreferredUnit, shiftCare:
guardianDateOfDeath = null,
checkedByAdmin = true,
confidential = false,
- createdDate = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
- modifiedDate = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
+ createdAt = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
+ createdBy = testDecisionMaker_1.toEvakaUser(),
+ modifiedAt = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
+ modifiedBy = testDecisionMaker_1.toEvakaUser(),
sentDate = LocalDate.of(2021, 1, 15),
dueDate = null,
dueDateSetManuallyAt = null,
@@ -144,8 +148,10 @@ val validPreschoolApplication =
guardianDateOfDeath = null,
checkedByAdmin = true,
confidential = false,
- createdDate = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
- modifiedDate = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
+ createdAt = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
+ createdBy = testDecisionMaker_1.toEvakaUser(),
+ modifiedAt = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
+ modifiedBy = testDecisionMaker_1.toEvakaUser(),
sentDate = LocalDate.of(2021, 1, 15),
dueDate = null,
dueDateSetManuallyAt = null,
@@ -239,8 +245,10 @@ fun validClubApplication(preferredUnit: DevDaycare, preferredStartDate: LocalDat
guardianDateOfDeath = null,
checkedByAdmin = true,
confidential = false,
- createdDate = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
- modifiedDate = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
+ createdAt = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
+ createdBy = testDecisionMaker_1.toEvakaUser(),
+ modifiedAt = HelsinkiDateTime.of(LocalDate.of(2021, 8, 15), LocalTime.of(12, 0)),
+ modifiedBy = testDecisionMaker_1.toEvakaUser(),
sentDate = LocalDate.of(2021, 1, 15),
dueDate = null,
dueDateSetManuallyAt = null,
diff --git a/service/src/main/kotlin/fi/espoo/evaka/application/Application.kt b/service/src/main/kotlin/fi/espoo/evaka/application/Application.kt
index b5939d2a427..6ffbb16c00a 100755
--- a/service/src/main/kotlin/fi/espoo/evaka/application/Application.kt
+++ b/service/src/main/kotlin/fi/espoo/evaka/application/Application.kt
@@ -112,8 +112,10 @@ data class ApplicationDetails(
val guardianDateOfDeath: LocalDate?,
val checkedByAdmin: Boolean,
val confidential: Boolean?,
- val createdDate: HelsinkiDateTime?,
- val modifiedDate: HelsinkiDateTime?,
+ val createdAt: HelsinkiDateTime?,
+ val createdBy: EvakaUser?,
+ val modifiedAt: HelsinkiDateTime?,
+ val modifiedBy: EvakaUser?,
val sentDate: LocalDate?,
val dueDate: LocalDate?,
val dueDateSetManuallyAt: HelsinkiDateTime?,
diff --git a/service/src/main/kotlin/fi/espoo/evaka/application/ApplicationQueries.kt b/service/src/main/kotlin/fi/espoo/evaka/application/ApplicationQueries.kt
index fd299ac7ae2..2f550257e51 100755
--- a/service/src/main/kotlin/fi/espoo/evaka/application/ApplicationQueries.kt
+++ b/service/src/main/kotlin/fi/espoo/evaka/application/ApplicationQueries.kt
@@ -81,8 +81,8 @@ fun Database.Transaction.insertApplication(
createUpdate {
sql(
"""
-INSERT INTO application (type, status, guardian_id, child_id, origin, created_by, hidefromguardian, sentdate, allow_other_guardian_access, document, form_modified, status_modified_at, status_modified_by, confidential)
-VALUES (${bind(type)}, 'CREATED', ${bind(guardianId)}, ${bind(childId)}, ${bind(origin)}, ${bind(createdBy)}, ${bind(hideFromGuardian)}, ${bind(sentDate)}, ${bind(allowOtherGuardianAccess)}, ${bindJson(document)}, ${bind(now)}, ${bind(now)}, ${bind(createdBy)}, NULL)
+INSERT INTO application (type, status, guardian_id, child_id, origin, created_at, created_by, hidefromguardian, sentdate, allow_other_guardian_access, document, modified_at, modified_by, status_modified_at, status_modified_by, confidential)
+VALUES (${bind(type)}, 'CREATED', ${bind(guardianId)}, ${bind(childId)}, ${bind(origin)}, ${bind(now)}, ${bind(createdBy)}, ${bind(hideFromGuardian)}, ${bind(sentDate)}, ${bind(allowOtherGuardianAccess)}, ${bindJson(document)}, ${bind(now)}, ${bind(createdBy)}, ${bind(now)}, ${bind(createdBy)}, NULL)
RETURNING id
"""
)
@@ -707,8 +707,8 @@ SELECT
) AS start_date,
a.sentDate,
a.status AS application_status,
- a.created AS created_date,
- a.form_modified AS modified_date,
+ a.created_at AS created_date,
+ a.modified_at AS modified_date,
a.transferapplication
FROM application a
WHERE (a.guardian_id = ${bind(citizenId)} OR EXISTS (
@@ -775,8 +775,14 @@ fun Database.Read.fetchApplicationDetails(
a.transferapplication,
a.additionaldaycareapplication,
a.hidefromguardian,
- a.created,
- a.form_modified,
+ a.created_at,
+ e_created.id AS created_by_id,
+ e_created.name AS created_by_name,
+ e_created.type AS created_by_type,
+ a.modified_at,
+ e_modified.id AS modified_by_id,
+ e_modified.name AS modified_by_name,
+ e_modified.type AS modified_by_type,
a.sentdate,
a.duedate,
a.duedate_set_manually_at,
@@ -788,6 +794,8 @@ fun Database.Read.fetchApplicationDetails(
FROM application a
LEFT JOIN person c ON c.id = a.child_id
LEFT JOIN person g1 ON g1.id = a.guardian_id
+ LEFT JOIN evaka_user e_created ON a.created_by = e_created.id
+ LEFT JOIN evaka_user e_modified ON a.modified_by = e_modified.id
LEFT JOIN (
SELECT application_id, jsonb_agg(jsonb_build_object(
'id', attachment.id,
@@ -835,8 +843,20 @@ fun Database.Read.fetchApplicationDetails(
guardianDateOfDeath = column("guardian_date_of_death"),
transferApplication = column("transferapplication"),
additionalDaycareApplication = column("additionaldaycareapplication"),
- createdDate = column("created"),
- modifiedDate = column("form_modified"),
+ createdAt = column("created_at"),
+ createdBy =
+ EvakaUser(
+ id = column("created_by_id"),
+ name = column("created_by_name"),
+ type = column("created_by_type"),
+ ),
+ modifiedAt = column("modified_at"),
+ modifiedBy =
+ EvakaUser(
+ id = column("modified_by_id"),
+ name = column("modified_by_name"),
+ type = column("modified_by_type"),
+ ),
sentDate = column("sentdate"),
dueDate = column("duedate"),
dueDateSetManuallyAt = column("duedate_set_manually_at"),
@@ -994,6 +1014,7 @@ fun Database.Transaction.updateForm(
childRestricted: Boolean,
guardianRestricted: Boolean,
now: HelsinkiDateTime,
+ modifiedBy: EvakaUserId,
) {
check(getApplicationType(id) == formType) { "Invalid form type for the application" }
val transformedForm =
@@ -1005,7 +1026,7 @@ fun Database.Transaction.updateForm(
execute {
sql(
- "UPDATE application SET document = ${bindJson(transformedForm)}, form_modified = ${bind(now)} WHERE id = ${bind(id)}"
+ "UPDATE application SET document = ${bindJson(transformedForm)}, modified_at = ${bind(now)}, modified_by = ${bind(modifiedBy)} WHERE id = ${bind(id)}"
)
}
}
@@ -1013,6 +1034,8 @@ fun Database.Transaction.updateForm(
fun Database.Transaction.resetCheckedByAdminAndConfidentiality(
id: ApplicationId,
form: ApplicationForm,
+ now: HelsinkiDateTime,
+ modifiedBy: EvakaUserId,
) {
val confidential =
when {
@@ -1035,10 +1058,13 @@ fun Database.Transaction.resetCheckedByAdminAndConfidentiality(
execute {
sql(
"""
- UPDATE application
- SET checkedbyadmin = ${bind(!requiresManualChecking)}, confidential = ${bind(confidential)}
+ UPDATE application SET
+ checkedbyadmin = ${bind(!requiresManualChecking)},
+ modified_at = ${bind(now)},
+ modified_by = ${bind(modifiedBy)},
+ confidential = ${bind(confidential)}
WHERE id = ${bind(id)}
- """
+ """
)
}
}
@@ -1054,7 +1080,9 @@ fun Database.Transaction.updateApplicationStatus(
UPDATE application SET
status = ${bind(status)},
status_modified_by = ${bind(modifiedBy)},
- status_modified_at = ${bind(now)}
+ status_modified_at = ${bind(now)},
+ modified_by = ${bind(modifiedBy)},
+ modified_at = ${bind(now)}
WHERE id = ${bind(id)}
"""
)
@@ -1064,10 +1092,12 @@ fun Database.Transaction.updateApplicationDates(
id: ApplicationId,
sentDate: LocalDate,
dueDate: LocalDate?,
+ now: HelsinkiDateTime,
+ modifiedBy: EvakaUserId,
) {
execute {
sql(
- "UPDATE application SET sentdate = ${bind(sentDate)}, duedate = ${bind(dueDate)} WHERE id = ${bind(id)}"
+ "UPDATE application SET sentdate = ${bind(sentDate)}, duedate = ${bind(dueDate)}, modified_at = ${bind(now)}, modified_by = ${bind(modifiedBy)} WHERE id = ${bind(id)}"
)
}
}
@@ -1075,13 +1105,17 @@ fun Database.Transaction.updateApplicationDates(
fun Database.Transaction.updateApplicationFlags(
id: ApplicationId,
applicationFlags: ApplicationFlags,
+ now: HelsinkiDateTime,
+ modifiedBy: EvakaUserId,
) = execute {
sql(
"""
UPDATE application
SET
transferapplication = ${bind(applicationFlags.isTransferApplication)},
- additionaldaycareapplication = ${bind(applicationFlags.isAdditionalDaycareApplication)}
+ additionaldaycareapplication = ${bind(applicationFlags.isAdditionalDaycareApplication)},
+ modified_at = ${bind(now)},
+ modified_by = ${bind(modifiedBy)}
WHERE id = ${bind(id)}
"""
)
@@ -1090,11 +1124,15 @@ fun Database.Transaction.updateApplicationFlags(
fun Database.Transaction.updateApplicationAllowOtherGuardianAccess(
id: ApplicationId,
allowOtherGuardianAccess: Boolean,
+ now: HelsinkiDateTime,
+ modifiedBy: EvakaUserId,
) = execute {
sql(
"""
- UPDATE application
- SET allow_other_guardian_access = ${bind(allowOtherGuardianAccess)}
+ UPDATE application SET
+ allow_other_guardian_access = ${bind(allowOtherGuardianAccess)},
+ modified_at = ${bind(now)},
+ modified_by = ${bind(modifiedBy)}
WHERE id = ${bind(id)}
"""
)
@@ -1139,20 +1177,43 @@ AND other_citizen.id != application.guardian_id
}
}
-fun Database.Transaction.setApplicationVerified(id: ApplicationId, verified: Boolean) {
+fun Database.Transaction.setApplicationVerified(
+ id: ApplicationId,
+ verified: Boolean,
+ now: HelsinkiDateTime,
+ modifiedBy: EvakaUserId,
+) {
execute {
- sql("UPDATE application SET checkedByAdmin = ${bind(verified)} WHERE id = ${bind(id)}")
+ sql(
+ "UPDATE application SET checkedByAdmin = ${bind(verified)}, modified_at = ${bind(now)}, modified_by = ${bind(modifiedBy)} WHERE id = ${bind(id)}"
+ )
}
}
-fun Database.Transaction.setApplicationConfidentiality(id: ApplicationId, confidential: Boolean?) {
+fun Database.Transaction.setApplicationConfidentiality(
+ id: ApplicationId,
+ confidential: Boolean?,
+ now: HelsinkiDateTime,
+ modifiedBy: EvakaUserId,
+) {
execute {
- sql("UPDATE application SET confidential = ${bind(confidential)} WHERE id = ${bind(id)}")
+ sql(
+ "UPDATE application SET confidential = ${bind(confidential)}, modified_at = ${bind(now)}, modified_by = ${bind(modifiedBy)} WHERE id = ${bind(id)}"
+ )
}
}
-fun Database.Transaction.setApplicationProcessId(id: ApplicationId, processId: ArchivedProcessId) {
- execute { sql("UPDATE application SET process_id = ${bind(processId)} WHERE id = ${bind(id)}") }
+fun Database.Transaction.setApplicationProcessId(
+ id: ApplicationId,
+ processId: ArchivedProcessId,
+ now: HelsinkiDateTime,
+ modifiedBy: EvakaUserId,
+) {
+ execute {
+ sql(
+ "UPDATE application SET process_id = ${bind(processId)}, modified_at = ${bind(now)}, modified_by = ${bind(modifiedBy)} WHERE id = ${bind(id)}"
+ )
+ }
}
fun Database.Transaction.deleteApplication(id: ApplicationId) = execute {
@@ -1166,7 +1227,7 @@ fun Database.Transaction.removeOldDrafts(clock: EvakaClock) {
val applicationIds =
createQuery {
sql(
- "SELECT id FROM application WHERE status = 'CREATED' AND created < ${bind(clock.today())} - ${bind(thresholdDays)}"
+ "SELECT id FROM application WHERE status = 'CREATED' AND created_at < ${bind(clock.today())} - ${bind(thresholdDays)}"
)
}
.toList()
@@ -1238,7 +1299,9 @@ fun Database.Transaction.cancelOutdatedSentTransferApplications(
UPDATE application SET
status = ${bind(ApplicationStatus.CANCELLED)},
status_modified_by = ${bind(evakaUserId)},
- status_modified_at = ${bind(clock.now())}
+ status_modified_at = ${bind(clock.now())},
+ modified_by = ${bind(evakaUserId)},
+ modified_at = ${bind(clock.now())}
WHERE transferapplication
AND status = ANY('{SENT}')
AND NOT EXISTS (
@@ -1290,7 +1353,9 @@ fun Database.Transaction.cancelAllActiveTransferApplications(
UPDATE application SET
status = 'CANCELLED',
status_modified_by = ${bind(evakaUserId)},
- status_modified_at = ${bind(clock.now())}
+ status_modified_at = ${bind(clock.now())},
+ modified_by = ${bind(evakaUserId)},
+ modified_at = ${bind(clock.now())}
WHERE transferapplication
AND child_id = ${bind(childId)}
AND status = ANY(${bind(arrayOf(ApplicationStatus.SENT))}::application_status_type[])
diff --git a/service/src/main/kotlin/fi/espoo/evaka/application/ApplicationStateService.kt b/service/src/main/kotlin/fi/espoo/evaka/application/ApplicationStateService.kt
index 98d905cabe8..455476b678f 100755
--- a/service/src/main/kotlin/fi/espoo/evaka/application/ApplicationStateService.kt
+++ b/service/src/main/kotlin/fi/espoo/evaka/application/ApplicationStateService.kt
@@ -274,9 +274,14 @@ class ApplicationStateService(
personService.getGuardians(tx, user, application.childId)
val applicationFlags = tx.applicationFlags(application, currentDate)
- tx.updateApplicationFlags(application.id, applicationFlags)
+ tx.updateApplicationFlags(application.id, applicationFlags, clock.now(), user.evakaUserId)
- tx.resetCheckedByAdminAndConfidentiality(applicationId, application.form)
+ tx.resetCheckedByAdminAndConfidentiality(
+ applicationId,
+ application.form,
+ clock.now(),
+ user.evakaUserId,
+ )
val sentDate = application.sentDate ?: currentDate
val dueDate =
@@ -289,7 +294,7 @@ class ApplicationStateService(
applicationFlags.isTransferApplication,
application.attachments,
)
- tx.updateApplicationDates(application.id, sentDate, dueDate)
+ tx.updateApplicationDates(application.id, sentDate, dueDate, clock.now(), user.evakaUserId)
tx.getPersonById(application.guardianId)?.let {
val email =
@@ -374,7 +379,7 @@ class ApplicationStateService(
now = clock.now(),
userId = user.evakaUserId,
)
- tx.setApplicationProcessId(applicationId, processId)
+ tx.setApplicationProcessId(applicationId, processId, clock.now(), user.evakaUserId)
}
Audit.ApplicationSend.log(targetId = AuditId(applicationId))
@@ -387,11 +392,11 @@ class ApplicationStateService(
application: ApplicationDetails,
) {
val applicationFlags = tx.applicationFlags(application, clock.today())
- tx.updateApplicationFlags(application.id, applicationFlags)
+ tx.updateApplicationFlags(application.id, applicationFlags, clock.now(), user.evakaUserId)
val sentDate = application.sentDate!!
val dueDate = application.sentDate
- tx.updateApplicationDates(application.id, sentDate, dueDate)
+ tx.updateApplicationDates(application.id, sentDate, dueDate, clock.now(), user.evakaUserId)
if (!application.hideFromGuardian) {
messageService.sendMessageAsEmployee(
@@ -421,7 +426,12 @@ class ApplicationStateService(
)
}
- tx.resetCheckedByAdminAndConfidentiality(application.id, application.form)
+ tx.resetCheckedByAdminAndConfidentiality(
+ application.id,
+ application.form,
+ clock.now(),
+ user.evakaUserId,
+ )
tx.updateApplicationStatus(application.id, SENT, user.evakaUserId, clock.now())
}
@@ -454,7 +464,12 @@ class ApplicationStateService(
)
)
- tx.resetCheckedByAdminAndConfidentiality(applicationId, application.form)
+ tx.resetCheckedByAdminAndConfidentiality(
+ applicationId,
+ application.form,
+ clock.now(),
+ user.evakaUserId,
+ )
asyncJobRunner.plan(
tx,
@@ -495,7 +510,12 @@ class ApplicationStateService(
val application = getApplication(tx, applicationId)
verifyStatus(application, setOf(WAITING_PLACEMENT, CANCELLED))
- tx.resetCheckedByAdminAndConfidentiality(applicationId, application.form)
+ tx.resetCheckedByAdminAndConfidentiality(
+ applicationId,
+ application.form,
+ clock.now(),
+ user.evakaUserId,
+ )
if (application.status == CANCELLED) {
tx.getArchiveProcessByApplicationId(applicationId)?.also { process ->
@@ -531,9 +551,19 @@ class ApplicationStateService(
if (application.confidential == null) {
when {
user is AuthenticatedUser.Citizen ->
- tx.setApplicationConfidentiality(applicationId, true)
+ tx.setApplicationConfidentiality(
+ applicationId,
+ true,
+ clock.now(),
+ user.evakaUserId,
+ )
confidential != null ->
- tx.setApplicationConfidentiality(applicationId, confidential)
+ tx.setApplicationConfidentiality(
+ applicationId,
+ confidential,
+ clock.now(),
+ user.evakaUserId,
+ )
else -> throw BadRequest("Confidentiality must be set")
}
} else if (confidential != null) throw BadRequest("Confidentiality is already set")
@@ -574,11 +604,16 @@ class ApplicationStateService(
if (application.confidential == null) {
if (confidential != null) {
- tx.setApplicationConfidentiality(applicationId, confidential)
+ tx.setApplicationConfidentiality(
+ applicationId,
+ confidential,
+ clock.now(),
+ user.evakaUserId,
+ )
} else throw BadRequest("Confidentiality must be set")
} else if (confidential != null) throw BadRequest("Confidentiality is already set")
- tx.setApplicationVerified(applicationId, true)
+ tx.setApplicationVerified(applicationId, true, clock.now(), user.evakaUserId)
Audit.ApplicationAdminDetailsUpdate.log(targetId = AuditId(applicationId))
}
@@ -1106,8 +1141,13 @@ class ApplicationStateService(
}
}
- tx.updateApplicationAllowOtherGuardianAccess(applicationId, update.allowOtherGuardianAccess)
- tx.updateApplicationContents(now, original, updatedForm)
+ tx.updateApplicationAllowOtherGuardianAccess(
+ applicationId,
+ update.allowOtherGuardianAccess,
+ now,
+ user.evakaUserId,
+ )
+ tx.updateApplicationContents(now, user.evakaUserId, original, updatedForm)
return getApplication(tx, applicationId)
}
@@ -1152,6 +1192,7 @@ class ApplicationStateService(
tx.updateApplicationContents(
now,
+ user.evakaUserId,
original,
updatedForm,
manuallySetDueDate = update.dueDate,
@@ -1168,6 +1209,7 @@ class ApplicationStateService(
private fun Database.Transaction.updateApplicationContents(
now: HelsinkiDateTime,
+ modifiedBy: EvakaUserId,
original: ApplicationDetails,
updatedForm: ApplicationForm,
manuallySetDueDate: LocalDate? = null,
@@ -1183,8 +1225,10 @@ class ApplicationStateService(
original.childRestricted,
original.guardianRestricted,
now,
+ modifiedBy,
)
- resetCheckedByAdminAndConfidentiality(original.id, updatedForm)
+
+ resetCheckedByAdminAndConfidentiality(original.id, updatedForm, now, modifiedBy)
when (manuallySetDueDate) {
null ->
// We don't want to calculate the due date for applications in the CREATED state.
diff --git a/service/src/main/kotlin/fi/espoo/evaka/espoo/bi/EspooBi.kt b/service/src/main/kotlin/fi/espoo/evaka/espoo/bi/EspooBi.kt
index 29e3d4a6a49..05d0ea45794 100644
--- a/service/src/main/kotlin/fi/espoo/evaka/espoo/bi/EspooBi.kt
+++ b/service/src/main/kotlin/fi/espoo/evaka/espoo/bi/EspooBi.kt
@@ -115,7 +115,7 @@ FROM daycare_caretaker
sql(
"""
SELECT
- id, created, updated, type, transferapplication, origin, status, additionaldaycareapplication, sentdate, duedate,
+ id, created_at, updated_at, type, transferapplication, origin, status, additionaldaycareapplication, sentdate, duedate,
(
SELECT array_agg(e::UUID)
FROM jsonb_array_elements_text(document -> 'apply' -> 'preferredUnits') e
diff --git a/service/src/main/kotlin/fi/espoo/evaka/espoo/bi/EspooBiModels.kt b/service/src/main/kotlin/fi/espoo/evaka/espoo/bi/EspooBiModels.kt
index 6ed0fe8b2b3..be15d7c3f4f 100644
--- a/service/src/main/kotlin/fi/espoo/evaka/espoo/bi/EspooBiModels.kt
+++ b/service/src/main/kotlin/fi/espoo/evaka/espoo/bi/EspooBiModels.kt
@@ -121,8 +121,8 @@ data class BiGroupCaretakerAllocation(
data class BiApplication(
val id: UUID,
- val created: HelsinkiDateTime,
- val updated: HelsinkiDateTime,
+ val createdAt: HelsinkiDateTime,
+ val updatedAt: HelsinkiDateTime,
val type: ApplicationType,
val transferApplication: Boolean,
val origin: ApplicationOrigin,
diff --git a/service/src/main/kotlin/fi/espoo/evaka/pis/ParentshipQueries.kt b/service/src/main/kotlin/fi/espoo/evaka/pis/ParentshipQueries.kt
index c4cb0cf4eb0..01d9860bafb 100644
--- a/service/src/main/kotlin/fi/espoo/evaka/pis/ParentshipQueries.kt
+++ b/service/src/main/kotlin/fi/espoo/evaka/pis/ParentshipQueries.kt
@@ -56,7 +56,7 @@ SELECT
created_by_user.name AS created_by_user_name,
modified_by_user.name AS modified_by_user_name,
created_by_application.type AS created_by_application_type,
- created_by_application.created AS created_by_application_created
+ created_by_application.created_at AS created_by_application_created
FROM fridge_child fc
JOIN person child ON fc.child_id = child.id
JOIN person head ON fc.head_of_child = head.id
diff --git a/service/src/main/kotlin/fi/espoo/evaka/pis/PartnershipQueries.kt b/service/src/main/kotlin/fi/espoo/evaka/pis/PartnershipQueries.kt
index 6cd5a3754c3..1de2e59db0d 100644
--- a/service/src/main/kotlin/fi/espoo/evaka/pis/PartnershipQueries.kt
+++ b/service/src/main/kotlin/fi/espoo/evaka/pis/PartnershipQueries.kt
@@ -37,7 +37,7 @@ fun Database.Read.getPartnership(id: PartnershipId): Partnership? {
(SELECT name FROM evaka_user WHERE id = fp1.modified_by) AS modified_by_name,
fp1.created_from_application,
a.type AS created_from_application_type,
- a.created AS created_from_application_created
+ a.created_at AS created_from_application_created
FROM fridge_partner fp1
JOIN fridge_partner fp2 ON fp1.partnership_id = fp2.partnership_id AND fp1.indx = 1 AND fp2.indx = 2
JOIN person p1 ON fp1.person_id = p1.id
@@ -74,7 +74,7 @@ SELECT
(SELECT name FROM evaka_user WHERE id = fp1.modified_by) AS modified_by_name,
fp1.created_from_application,
a.type AS created_from_application_type,
- a.created AS created_from_application_created
+ a.created_at AS created_from_application_created
FROM fridge_partner fp1
JOIN fridge_partner fp2 ON fp1.partnership_id = fp2.partnership_id AND fp1.indx = 1 AND fp2.indx = 2
JOIN person p1 ON fp1.person_id = p1.id
@@ -102,7 +102,7 @@ SELECT
(SELECT name FROM evaka_user WHERE id = fp.created_by) AS created_by_name,
(SELECT name FROM evaka_user WHERE id = fp.modified_by) AS modified_by_name,
a.type AS created_from_application_type,
- a.created AS created_from_application_created
+ a.created_at AS created_from_application_created
FROM fridge_partner fp
JOIN fridge_partner partner ON fp.partnership_id = partner.partnership_id AND fp.indx != partner.indx
JOIN person p ON partner.person_id = p.id
@@ -161,7 +161,7 @@ fun Database.Transaction.createPartnership(
(SELECT name FROM evaka_user WHERE id = fp1.modified_by) AS modified_by_name,
fp1.created_from_application,
a.type AS created_from_application_type,
- a.created AS created_from_application_created
+ a.created_at AS created_from_application_created
FROM new_fridge_partner fp1
JOIN new_fridge_partner fp2 ON fp1.partnership_id = fp2.partnership_id AND fp1.indx = 1 AND fp2.indx = 2
JOIN person p1 ON fp1.person_id = p1.id
diff --git a/service/src/main/kotlin/fi/espoo/evaka/process/ProcessMetadataController.kt b/service/src/main/kotlin/fi/espoo/evaka/process/ProcessMetadataController.kt
index 17b870596ac..c09ee06892b 100644
--- a/service/src/main/kotlin/fi/espoo/evaka/process/ProcessMetadataController.kt
+++ b/service/src/main/kotlin/fi/espoo/evaka/process/ProcessMetadataController.kt
@@ -340,7 +340,7 @@ class ProcessMetadataController(private val accessControl: AccessControl) {
WHEN a.type = 'CLUB'
THEN 'Kerhohakemus'
END AS name,
- coalesce(a.sentdate at time zone 'europe/helsinki', a.created) AS created_at,
+ coalesce(a.sentdate at time zone 'europe/helsinki', a.created_at) AS created_at,
e.id AS created_by_id,
e.name AS created_by_name,
e.type AS created_by_type,
diff --git a/service/src/main/kotlin/fi/espoo/evaka/shared/dev/DataInitializers.kt b/service/src/main/kotlin/fi/espoo/evaka/shared/dev/DataInitializers.kt
index 4bc0127820d..5861b9cc7be 100755
--- a/service/src/main/kotlin/fi/espoo/evaka/shared/dev/DataInitializers.kt
+++ b/service/src/main/kotlin/fi/espoo/evaka/shared/dev/DataInitializers.kt
@@ -426,13 +426,14 @@ fun Database.Transaction.insertTestApplication(
transferApplication: Boolean = false,
allowOtherGuardianAccess: Boolean = true,
document: DatabaseForm,
- formModified: HelsinkiDateTime = HelsinkiDateTime.now(),
+ modifiedAt: HelsinkiDateTime = HelsinkiDateTime.now(),
+ modifiedBy: EvakaUserId = AuthenticatedUser.SystemInternalUser.evakaUserId,
): ApplicationId {
createUpdate {
sql(
"""
-INSERT INTO application (type, id, sentdate, duedate, status, guardian_id, child_id, origin, hidefromguardian, additionalDaycareApplication, transferApplication, allow_other_guardian_access, document, form_modified, confidential)
-VALUES (${bind(type)}, ${bind(id)}, ${bind(sentDate)}, ${bind(dueDate)}, ${bind(status)}::application_status_type, ${bind(guardianId)}, ${bind(childId)}, 'ELECTRONIC'::application_origin_type, ${bind(hideFromGuardian)}, ${bind(additionalDaycareApplication)}, ${bind(transferApplication)}, ${bind(allowOtherGuardianAccess)}, ${bindJson(document)}, ${bind(formModified)}, NULL)
+INSERT INTO application (type, id, sentdate, duedate, status, guardian_id, child_id, origin, hidefromguardian, additionalDaycareApplication, transferApplication, allow_other_guardian_access, document, modified_at, modified_by, created_at, created_by, confidential)
+VALUES (${bind(type)}, ${bind(id)}, ${bind(sentDate)}, ${bind(dueDate)}, ${bind(status)}::application_status_type, ${bind(guardianId)}, ${bind(childId)}, 'ELECTRONIC'::application_origin_type, ${bind(hideFromGuardian)}, ${bind(additionalDaycareApplication)}, ${bind(transferApplication)}, ${bind(allowOtherGuardianAccess)}, ${bindJson(document)}, ${bind(modifiedAt)}, ${bind(modifiedBy)}, ${bind(modifiedAt)}, ${bind(modifiedBy)}, NULL)
"""
)
}
@@ -947,7 +948,10 @@ INSERT INTO application(
transferapplication,
allow_other_guardian_access,
document,
- form_modified
+ created_at,
+ created_by,
+ modified_at,
+ modified_by
)
VALUES (
${bind(application.id)},
@@ -964,7 +968,10 @@ VALUES (
${bind(application.transferApplication)},
${bind(application.allowOtherGuardianAccess)},
${bindJson(document)},
- ${bind(application.formModified)}
+ ${bind(application.createdAt)},
+ ${bind(application.createdBy)},
+ ${bind(application.modifiedAt)},
+ ${bind(application.modifiedBy)}
)
"""
)
diff --git a/service/src/main/kotlin/fi/espoo/evaka/shared/dev/DevApi.kt b/service/src/main/kotlin/fi/espoo/evaka/shared/dev/DevApi.kt
index 3b014e14382..bb419238989 100755
--- a/service/src/main/kotlin/fi/espoo/evaka/shared/dev/DevApi.kt
+++ b/service/src/main/kotlin/fi/espoo/evaka/shared/dev/DevApi.kt
@@ -2119,8 +2119,10 @@ data class PlacementPlan(
data class DevApplicationWithForm(
val id: ApplicationId,
val type: ApplicationType,
- val createdDate: HelsinkiDateTime?,
- val modifiedDate: HelsinkiDateTime?,
+ val createdAt: HelsinkiDateTime,
+ val createdBy: EvakaUserId,
+ val modifiedAt: HelsinkiDateTime,
+ val modifiedBy: EvakaUserId,
var sentDate: LocalDate?,
var dueDate: LocalDate?,
val status: ApplicationStatus,
@@ -2134,7 +2136,6 @@ data class DevApplicationWithForm(
val allowOtherGuardianAccess: Boolean = true,
val otherGuardians: List,
val form: ApplicationForm,
- val formModified: HelsinkiDateTime,
)
data class DevDaycareGroupAcl(
diff --git a/service/src/main/resources/db/migration/R__application_view.sql b/service/src/main/resources/db/migration/R__application_view.sql
index a0fdcb8d4c8..9ae0c9984dd 100755
--- a/service/src/main/resources/db/migration/R__application_view.sql
+++ b/service/src/main/resources/db/migration/R__application_view.sql
@@ -4,7 +4,7 @@ CREATE OR REPLACE VIEW application_view (
id,
document,
docVersion,
- created,
+ created_at,
formModified,
sentDate,
dueDate,
@@ -49,7 +49,7 @@ SELECT
id,
document,
docVersion,
- created,
+ created_at,
formModified,
sentDate,
dueDate,
@@ -108,8 +108,8 @@ SELECT
appl.id,
appl.document,
appl.document -> 'docVersion' AS docVersion,
- appl.form_modified AS formModified,
- appl.created,
+ appl.modified_at AS formModified,
+ appl.created_at,
appl.sentDate,
appl.dueDate,
appl.status AS status,
diff --git a/service/src/main/resources/db/migration/V475__application_modified_metadata.sql b/service/src/main/resources/db/migration/V475__application_modified_metadata.sql
new file mode 100644
index 00000000000..bc61dfe225a
--- /dev/null
+++ b/service/src/main/resources/db/migration/V475__application_modified_metadata.sql
@@ -0,0 +1,20 @@
+ALTER TABLE application RENAME COLUMN form_modified TO modified_at;
+
+ALTER TABLE application ADD COLUMN modified_by UUID REFERENCES evaka_user;
+
+UPDATE application SET
+ created_by = COALESCE(created_by, '00000000-0000-0000-0000-000000000000'::UUID),
+ modified_by = COALESCE(modified_by, created_by, '00000000-0000-0000-0000-000000000000'::UUID);
+
+ALTER TABLE application
+ ALTER COLUMN created_by SET NOT NULL,
+ ALTER COLUMN modified_by SET NOT NULL;
+
+CREATE INDEX fk$application_modified_by ON application(modified_by);
+
+
+ALTER TABLE application RENAME COLUMN created TO created_at;
+
+DROP TRIGGER set_timestamp ON application;
+ALTER TABLE application RENAME COLUMN updated TO updated_at;
+CREATE TRIGGER set_timestamp BEFORE UPDATE ON application FOR EACH ROW EXECUTE PROCEDURE trigger_refresh_updated_at();
diff --git a/service/src/main/resources/migrations.txt b/service/src/main/resources/migrations.txt
index ba86afa7e1c..41ed3d02d49 100644
--- a/service/src/main/resources/migrations.txt
+++ b/service/src/main/resources/migrations.txt
@@ -470,3 +470,4 @@ V471__application_confidentiality.sql
V472__employee_ssn.sql
V473__person_municipality_of_residence.sql
V474__holiday_questionnaire_open_ranges.sql
+V475__application_modified_metadata.sql