From 7cf0e92dd1e8e853d2bd04d720ae0f109dd8c0d7 Mon Sep 17 00:00:00 2001
From: Jarkko Pesonen <435495+jrkkp@users.noreply.github.com>
Date: Mon, 4 Nov 2024 09:56:07 +0200
Subject: [PATCH] VKT(Frontend & Backend): Enrollment appointment clerk
interface
---
.../api/clerk/ClerkEnrollmentController.java | 2 +-
.../oph/vkt/model/EnrollmentAppointment.java | 6 ++++
.../vkt/service/ClerkEnrollmentService.java | 4 +++
.../fi/oph/vkt/util/ClerkEnrollmentUtil.java | 6 ++--
.../db/changelog/db.changelog-1.0.xml | 6 ++++
.../ClerkEnrollmentContactRequestPage.tsx | 29 +++++++++++++++++--
.../reducers/clerkEnrollmentContactRequest.ts | 12 ++++++++
.../sagas/clerkEnrollmentContactRequest.ts | 27 +++++++++++++++++
8 files changed, 86 insertions(+), 6 deletions(-)
diff --git a/backend/vkt/src/main/java/fi/oph/vkt/api/clerk/ClerkEnrollmentController.java b/backend/vkt/src/main/java/fi/oph/vkt/api/clerk/ClerkEnrollmentController.java
index af482d4f1..4fec6bd38 100644
--- a/backend/vkt/src/main/java/fi/oph/vkt/api/clerk/ClerkEnrollmentController.java
+++ b/backend/vkt/src/main/java/fi/oph/vkt/api/clerk/ClerkEnrollmentController.java
@@ -84,7 +84,7 @@ public ClerkEnrollmentContactRequestDTO getEnrollmentContactRequest(@PathVariabl
return clerkEnrollmentService.getEnrollmentContactRequest(enrollmentContactId);
}
- @PutMapping(path = "/contact/{enrollmentContactId:\\d+}/convertToAppointment")
+ @PostMapping(path = "/contact/{enrollmentContactId:\\d+}/convertToAppointment", consumes = ALL_VALUE)
@Operation(tags = TAG_ENROLLMENT, summary = "Get enrollment contact request")
public ClerkEnrollmentAppointmentDTO enrollmentContactRequestToAppointment(
@PathVariable final long enrollmentContactId
diff --git a/backend/vkt/src/main/java/fi/oph/vkt/model/EnrollmentAppointment.java b/backend/vkt/src/main/java/fi/oph/vkt/model/EnrollmentAppointment.java
index 0cca97896..78a5c1aa9 100644
--- a/backend/vkt/src/main/java/fi/oph/vkt/model/EnrollmentAppointment.java
+++ b/backend/vkt/src/main/java/fi/oph/vkt/model/EnrollmentAppointment.java
@@ -58,6 +58,12 @@ public class EnrollmentAppointment extends EnrollmentCommon {
@Column(name = "country")
private String country;
+ @Column(name = "first_name")
+ private String firstName;
+
+ @Column(name = "last_name")
+ private String lastName;
+
@Size(max = 255)
@Column(name = "auth_hash", unique = true)
private String authHash;
diff --git a/backend/vkt/src/main/java/fi/oph/vkt/service/ClerkEnrollmentService.java b/backend/vkt/src/main/java/fi/oph/vkt/service/ClerkEnrollmentService.java
index 2dfc3fa3c..e468df2f1 100644
--- a/backend/vkt/src/main/java/fi/oph/vkt/service/ClerkEnrollmentService.java
+++ b/backend/vkt/src/main/java/fi/oph/vkt/service/ClerkEnrollmentService.java
@@ -227,6 +227,7 @@ public void getAndSaveKoskiEducationDetailsForEnrollment(final long enrollmentId
koskiService.saveEducationsForEnrollment(freeEnrollment, enrollment.getExamEvent().getId(), educationDTOs);
}
+ @Transactional(readOnly = true)
public ClerkEnrollmentContactRequestDTO getEnrollmentContactRequest(final long enrollmentContactId) {
final EnrollmentAppointment enrollmentAppointment = enrollmentAppointmentRepository.getReferenceById(
enrollmentContactId
@@ -235,6 +236,7 @@ public ClerkEnrollmentContactRequestDTO getEnrollmentContactRequest(final long e
return ClerkEnrollmentUtil.createClerkEnrollmentContactDTO(enrollmentAppointment);
}
+ @Transactional
public ClerkEnrollmentAppointmentDTO convertToAppointment(final long enrollmentContactId) {
final EnrollmentAppointment enrollmentAppointment = enrollmentAppointmentRepository.getReferenceById(
enrollmentContactId
@@ -246,6 +248,7 @@ public ClerkEnrollmentAppointmentDTO convertToAppointment(final long enrollmentC
return ClerkEnrollmentUtil.createClerkEnrollmentAppointmentDTO(enrollmentAppointment);
}
+ @Transactional(readOnly = true)
public ClerkEnrollmentAppointmentDTO getEnrollmentAppointment(final long enrollmentAppointmentId) {
final EnrollmentAppointment enrollmentAppointment = enrollmentAppointmentRepository.getReferenceById(
enrollmentAppointmentId
@@ -254,6 +257,7 @@ public ClerkEnrollmentAppointmentDTO getEnrollmentAppointment(final long enrollm
return ClerkEnrollmentUtil.createClerkEnrollmentAppointmentDTO(enrollmentAppointment);
}
+ @Transactional
public ClerkEnrollmentAppointmentDTO updateAppointment(final ClerkEnrollmentAppointmentUpdateDTO dto) {
final EnrollmentAppointment enrollmentAppointment = enrollmentAppointmentRepository.getReferenceById(dto.id());
diff --git a/backend/vkt/src/main/java/fi/oph/vkt/util/ClerkEnrollmentUtil.java b/backend/vkt/src/main/java/fi/oph/vkt/util/ClerkEnrollmentUtil.java
index 30915bfe7..550d493c8 100644
--- a/backend/vkt/src/main/java/fi/oph/vkt/util/ClerkEnrollmentUtil.java
+++ b/backend/vkt/src/main/java/fi/oph/vkt/util/ClerkEnrollmentUtil.java
@@ -172,8 +172,8 @@ public static ClerkEnrollmentAppointmentDTO createClerkEnrollmentAppointmentDTO(
.readingComprehensionPartialExam(enrollmentAppointment.isReadingComprehensionPartialExam())
.status(enrollmentAppointment.getStatus())
.email(enrollmentAppointment.getEmail())
- .firstName(enrollmentAppointment.getPerson().getFirstName())
- .lastName(enrollmentAppointment.getPerson().getLastName())
+ .firstName(enrollmentAppointment.getFirstName())
+ .lastName(enrollmentAppointment.getLastName())
.payments(paymentDTOs)
.build();
}
@@ -195,6 +195,8 @@ public static ClerkEnrollmentContactRequestDTO createClerkEnrollmentContactDTO(
.readingComprehensionPartialExam(enrollmentAppointment.isReadingComprehensionPartialExam())
.status(enrollmentAppointment.getStatus())
.email(enrollmentAppointment.getEmail())
+ .firstName(enrollmentAppointment.getFirstName())
+ .lastName(enrollmentAppointment.getLastName())
.build();
}
}
diff --git a/backend/vkt/src/main/resources/db/changelog/db.changelog-1.0.xml b/backend/vkt/src/main/resources/db/changelog/db.changelog-1.0.xml
index 642c4637f..b175dfc21 100644
--- a/backend/vkt/src/main/resources/db/changelog/db.changelog-1.0.xml
+++ b/backend/vkt/src/main/resources/db/changelog/db.changelog-1.0.xml
@@ -918,4 +918,10 @@
+
+
+
+
+
+
diff --git a/frontend/packages/vkt/src/pages/ClerkEnrollmentContactRequestPage.tsx b/frontend/packages/vkt/src/pages/ClerkEnrollmentContactRequestPage.tsx
index 7b906f1b5..d7cfd449e 100644
--- a/frontend/packages/vkt/src/pages/ClerkEnrollmentContactRequestPage.tsx
+++ b/frontend/packages/vkt/src/pages/ClerkEnrollmentContactRequestPage.tsx
@@ -1,7 +1,7 @@
import { ArrowBackIosOutlined as ArrowBackIosOutlinedIcon } from '@mui/icons-material';
import { Box, Divider, Grid, Paper } from '@mui/material';
import { FC, useEffect } from 'react';
-import { useParams } from 'react-router';
+import { useNavigate, useParams } from 'react-router';
import {
CustomButton,
CustomButtonLink,
@@ -16,7 +16,10 @@ import { APIResponseStatus, Color, Variant } from 'shared/enums';
import { useCommonTranslation } from 'configs/i18n';
import { useAppDispatch, useAppSelector } from 'configs/redux';
import { AppRoutes } from 'enums/app';
-import { loadClerkEnrollmentContactRequest } from 'redux/reducers/clerkEnrollmentContactRequest';
+import {
+ createClerkEnrollmentAppointment,
+ loadClerkEnrollmentContactRequest,
+} from 'redux/reducers/clerkEnrollmentContactRequest';
import { clerkEnrollmentContactRequestSelector } from 'redux/selectors/clerkEnrollmentContactRequest';
const BackButton = () => {
@@ -36,11 +39,12 @@ const BackButton = () => {
};
export const ClerkEnrollmentContactRequestPage: FC = () => {
- const { status, enrollment } = useAppSelector(
+ const { status, createStatus, enrollment } = useAppSelector(
clerkEnrollmentContactRequestSelector,
);
const translateCommon = useCommonTranslation();
const params = useParams();
+ const navigate = useNavigate();
const dispatch = useAppDispatch();
@@ -55,6 +59,20 @@ export const ClerkEnrollmentContactRequestPage: FC = () => {
}
}, [dispatch, status, params.enrollmentContactRequestId]);
+ useEffect(() => {
+ if (
+ createStatus === APIResponseStatus.Success &&
+ params.enrollmentContactRequestId
+ ) {
+ navigate(
+ AppRoutes.ClerkEnrollmentAppointmentPage.replace(
+ ':enrollmentAppointmentId',
+ params.enrollmentContactRequestId,
+ ),
+ );
+ }
+ }, [dispatch, navigate, params.enrollmentContactRequestId, createStatus]);
+
const isLoading = status === APIResponseStatus.InProgress;
const isSavingDisabled = isLoading;
@@ -62,6 +80,10 @@ export const ClerkEnrollmentContactRequestPage: FC = () => {
return <>>;
}
+ const onSubmit = () => {
+ dispatch(createClerkEnrollmentAppointment(enrollment.id));
+ };
+
return (
{
variant={Variant.Contained}
color={Color.Secondary}
disabled={isSavingDisabled}
+ onClick={onSubmit}
>
{translateCommon('save')}
diff --git a/frontend/packages/vkt/src/redux/reducers/clerkEnrollmentContactRequest.ts b/frontend/packages/vkt/src/redux/reducers/clerkEnrollmentContactRequest.ts
index 5461b0510..311424ffb 100644
--- a/frontend/packages/vkt/src/redux/reducers/clerkEnrollmentContactRequest.ts
+++ b/frontend/packages/vkt/src/redux/reducers/clerkEnrollmentContactRequest.ts
@@ -34,6 +34,15 @@ const clerkEnrollmentContactRequestSlice = createSlice({
createClerkEnrollmentAppointment(state, _action: PayloadAction) {
state.createStatus = APIResponseStatus.InProgress;
},
+ storeCreateClerkEnrollmentAppointment(
+ state,
+ _action: PayloadAction,
+ ) {
+ state.createStatus = APIResponseStatus.Success;
+ },
+ rejectCreateClerkEnrollmentAppointment(state) {
+ state.createStatus = APIResponseStatus.Error;
+ },
},
});
@@ -43,4 +52,7 @@ export const {
rejectClerkEnrollmentContactRequest,
storeClerkEnrollmentContactRequest,
loadClerkEnrollmentContactRequest,
+ createClerkEnrollmentAppointment,
+ storeCreateClerkEnrollmentAppointment,
+ rejectCreateClerkEnrollmentAppointment,
} = clerkEnrollmentContactRequestSlice.actions;
diff --git a/frontend/packages/vkt/src/redux/sagas/clerkEnrollmentContactRequest.ts b/frontend/packages/vkt/src/redux/sagas/clerkEnrollmentContactRequest.ts
index 6e7e38e6f..35de27dc1 100644
--- a/frontend/packages/vkt/src/redux/sagas/clerkEnrollmentContactRequest.ts
+++ b/frontend/packages/vkt/src/redux/sagas/clerkEnrollmentContactRequest.ts
@@ -6,12 +6,35 @@ import axiosInstance from 'configs/axios';
import { APIEndpoints } from 'enums/api';
import { ClerkEnrollmentContactResponse } from 'interfaces/clerkEnrollment';
import {
+ createClerkEnrollmentAppointment,
loadClerkEnrollmentContactRequest,
rejectClerkEnrollmentContactRequest,
+ rejectCreateClerkEnrollmentAppointment,
storeClerkEnrollmentContactRequest,
+ storeCreateClerkEnrollmentAppointment,
} from 'redux/reducers/clerkEnrollmentContactRequest';
import { SerializationUtils } from 'utils/serialization';
+function* createClerkEnrollmentAppointmentSaga(action: PayloadAction) {
+ try {
+ const contactId = action.payload;
+ const saveUrl = `${APIEndpoints.ClerkEnrollmentContactRequest}/${contactId}/convertToAppointment`;
+
+ const response: AxiosResponse = yield call(
+ axiosInstance.post,
+ saveUrl,
+ );
+ const enrollment =
+ SerializationUtils.deserializeClerkEnrollmentContactRequest(
+ response.data,
+ );
+
+ yield put(storeCreateClerkEnrollmentAppointment(enrollment));
+ } catch (error) {
+ yield put(rejectCreateClerkEnrollmentAppointment());
+ }
+}
+
function* loadClerkEnrollmentContactRequestSaga(action: PayloadAction) {
try {
const contactId = action.payload;
@@ -37,4 +60,8 @@ export function* watchClerkEnrollmentContactRequest() {
loadClerkEnrollmentContactRequest.type,
loadClerkEnrollmentContactRequestSaga,
);
+ yield takeLatest(
+ createClerkEnrollmentAppointment.type,
+ createClerkEnrollmentAppointmentSaga,
+ );
}