Skip to content

Commit

Permalink
VKT(Frontend & Backend): Various fixes, added audit logs, new demo da…
Browse files Browse the repository at this point in the history
…ta, fixed enrollment statuses
  • Loading branch information
jrkkp committed Nov 28, 2024
1 parent ce0970e commit 145079d
Show file tree
Hide file tree
Showing 12 changed files with 142 additions and 62 deletions.
62 changes: 56 additions & 6 deletions backend/vkt/db/4_init.sql
Original file line number Diff line number Diff line change
Expand Up @@ -436,6 +436,34 @@ VALUES (
'tammerkosken silta'
);

-- insert past examiner_exam_event
INSERT INTO examiner_exam_event(version, date, language, examiner_id, is_hidden, registration_closes, max_participants, municipality_id, location)
VALUES (
1,
NOW() - INTERVAL '2 weeks',
'FI',
1,
false,
NOW() - INTERVAL '1 weeks',
10,
2,
'Testimaa'
);

-- insert past examiner_exam_event
INSERT INTO examiner_exam_event(version, date, language, examiner_id, is_hidden, registration_closes, max_participants, municipality_id, location)
VALUES (
1,
NOW() - INTERVAL '3 weeks',
'FI',
1,
false,
NOW() - INTERVAL '2 weeks',
10,
2,
'Mordor'
);

-- Insert enrollment appointment
INSERT INTO enrollment_appointment(person_id, examiner_id,
skill_oral, skill_textual, skill_understanding,
Expand Down Expand Up @@ -465,7 +493,7 @@ VALUES (1, 1, 1,
'Teppo', 'Testinen',
'922c2089-83a8-4163-8180-d8b675ff5337', NOW() + INTERVAL '3 days', NOW());

-- Insert enrollment appointment
-- Insert multiple enrollment appointments for person 2
INSERT INTO enrollment_appointment(person_id, examiner_id, examiner_exam_event_id,
skill_oral, skill_textual, skill_understanding,
partial_exam_speaking, partial_exam_speech_comprehension, partial_exam_writing, partial_exam_reading_comprehension,
Expand All @@ -485,25 +513,47 @@ VALUES (2, null, 51400, '78b29334-a283-11ef-88a1-bf672bd574b1', '7676156682',
'https://pay.paytrail.com/pay/78b29334-a283-11ef-88a1-bf672bd574b1', 'OK',
null, 3);

-- Insert multiple enrollment appointments for person 2
INSERT INTO enrollment_appointment(person_id, examiner_id, examiner_exam_event_id,
skill_oral, skill_textual, skill_understanding,
partial_exam_speaking, partial_exam_speech_comprehension, partial_exam_writing, partial_exam_reading_comprehension,
status, digital_certificate_consent, email, phone_number, street, postal_code, town, country, first_name, last_name,
auth_hash, auth_hash_expires, auth_hash_sent, created_at)
VALUES (2, 1, 1,
false, true, false,
false, false, false, true,
VALUES (2, 1, 3,
true, true, true,
true, true, true, true,
'COMPLETED', false,
'[email protected]', '0401234504', null, null, null, null,
'Anneli', 'Annikkinen',
'22223089-83a8-4163-8180-d8b675ff5337', NOW() - INTERVAL '13 days', NOW() - INTERVAL '16 days',
'55523089-83a8-4163-8180-d8b675ff5337', NOW() - INTERVAL '13 days', NOW() - INTERVAL '16 days',
NOW() - INTERVAL '17 days');

INSERT INTO payment(version, enrollment_id, amount, transaction_id, reference, payment_url,
payment_status, refunded_at, enrollment_appointment_id)
VALUES (3, null, 51400, '12345634-a283-11ef-88a1-bf672bd574b1', '9676156682',
'https://pay.paytrail.com/pay/12345634-a283-11ef-88a1-bf672bd574b1', 'OK',
null, 3);
null, 4);

-- Insert multiple enrollment appointments for person 2
INSERT INTO enrollment_appointment(person_id, examiner_id, examiner_exam_event_id,
skill_oral, skill_textual, skill_understanding,
partial_exam_speaking, partial_exam_speech_comprehension, partial_exam_writing, partial_exam_reading_comprehension,
status, digital_certificate_consent, email, phone_number, street, postal_code, town, country, first_name, last_name,
auth_hash, auth_hash_expires, auth_hash_sent, created_at)
VALUES (2, 1, 4,
false, true, false,
false, false, false, true,
'COMPLETED', false,
'[email protected]', '0401234504', null, null, null, null,
'Anneli', 'Annikkinen',
'44423089-83a8-4163-8180-d8b675ff5337', NOW() - INTERVAL '13 days', NOW() - INTERVAL '16 days',
NOW() - INTERVAL '23 days');

INSERT INTO payment(version, enrollment_id, amount, transaction_id, reference, payment_url,
payment_status, refunded_at, enrollment_appointment_id)
VALUES (3, null, 51400, '99995634-a283-11ef-88a1-bf672bd574b1', '0006156682',
'https://pay.paytrail.com/pay/99945634-a283-11ef-88a1-bf672bd574b1', 'OK',
null, 5);

-- Insert enrollment appointment
INSERT INTO enrollment_appointment(person_id, examiner_id, examiner_exam_event_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public void deleteEnrollmentContactRequest(
@PostMapping(path = "/contact/{enrollmentContactId:\\d+}/convertToAppointment", consumes = ALL_VALUE)
@Operation(tags = TAG_ENROLLMENT, summary = "Convert enrollment contact request to enrollment appointment")
public ExaminerEnrollmentAppointmentDTO enrollmentContactRequestToAppointment(
@PathVariable String oid,
@PathVariable final String oid,
@PathVariable final long enrollmentContactId
) {
return examinerEnrollmentService.convertToAppointment(oid, enrollmentContactId);
Expand Down
4 changes: 4 additions & 0 deletions backend/vkt/src/main/java/fi/oph/vkt/audit/AuditService.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,10 @@ public void logById(final VktOperation operation, final long id) {
log(operation, new Target.Builder().setField("id", Long.toString(id)).build(), Changes.EMPTY);
}

public void logById(final VktOperation operation, final String id) {
log(operation, new Target.Builder().setField("id", id).build(), Changes.EMPTY);
}

public <T> void logUpdate(final VktOperation operation, final long id, final T dtoBefore, final T dtoAfter) {
log(
operation,
Expand Down
6 changes: 6 additions & 0 deletions backend/vkt/src/main/java/fi/oph/vkt/audit/VktOperation.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,10 @@ public enum VktOperation implements Operation {
UPDATE_ENROLLMENT_PAYMENT_LINK,
MOVE_ENROLLMENT,
REFUND_PAYMENT,
LIST_EXAMINER_DETAILS,
GET_EXAMINER_INITIAL_DETAILS,
VIEW_EXAMINER_CONTACT_REQUEST,
VIEW_EXAMINER_ENROLLMENT,
DELETE_EXAMINER_CONTACT_REQUEST,
VIEW_EXAMINER_ENROLLMENT_HISTORY,
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,6 @@ public enum EnrollmentAppointmentStatus {
EXPECTING_PAYMENT,
WAITING_AUTHENTICATION,
CANCELED_PAYMENT,
ENROLLMENT_CREATED,
CONTACT_CREATED,
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,30 @@
import fi.oph.vkt.model.type.EnrollmentAppointmentStatus;
import java.util.List;
import java.util.Optional;
import org.springframework.data.jpa.repository.Query;
import org.springframework.stereotype.Repository;

@Repository
public interface EnrollmentAppointmentRepository extends BaseRepository<EnrollmentAppointment> {
Optional<EnrollmentAppointment> findByIdAndAuthHashAndDeletedAtIsNull(final long id, final String paymentLinkHash);
List<EnrollmentAppointment> findByExaminerAndStatusAndDeletedAtIsNull(
final Examiner examiner,
final EnrollmentAppointmentStatus status
);
List<EnrollmentAppointment> findByPersonAndDeletedAtIsNull(final Person person);

@Query(
"SELECT e" +
" FROM EnrollmentAppointment e" +
" WHERE e.examiner = ?1" +
" AND e.status IN (fi.oph.vkt.model.type.EnrollmentAppointmentStatus.CONTACT_CREATED, fi.oph.vkt.model.type.EnrollmentAppointmentStatus.WAITING_AUTHENTICATION)" +
" AND e.deletedAt IS NULL" +
" ORDER BY e.createdAt DESC"
)
List<EnrollmentAppointment> findExaminerContactRequests(final Examiner examiner);

@Query(
"SELECT e" +
" FROM EnrollmentAppointment e" +
" WHERE e.person = ?1" +
" AND e.status IN (fi.oph.vkt.model.type.EnrollmentAppointmentStatus.COMPLETED)" +
" AND e.deletedAt IS NULL" +
" ORDER BY e.createdAt DESC"
)
List<EnrollmentAppointment> findPersonEnrollmentHistory(final Person person);
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import fi.oph.vkt.api.dto.examiner.ExaminerDetailsInitDTO;
import fi.oph.vkt.api.dto.examiner.ExaminerDetailsUpsertDTO;
import fi.oph.vkt.audit.AuditService;
import fi.oph.vkt.audit.VktOperation;
import fi.oph.vkt.model.EnrollmentAppointment;
import fi.oph.vkt.model.Examiner;
import fi.oph.vkt.model.type.EnrollmentAppointmentStatus;
Expand Down Expand Up @@ -41,14 +42,16 @@ private PersonalData getOnrPersonalData(final String oid) {

@Transactional(readOnly = true)
public ExaminerDetailsInitDTO getInitialExaminerPersonalData(final String oid) {
// TODO Audit log entry
if (examinerRepository.findByOid(oid).isPresent()) {
throw new APIException(APIExceptionType.EXAMINER_ALREADY_INITIALIZED);
}
PersonalData personalData = this.getOnrPersonalData(oid);
final PersonalData personalData = this.getOnrPersonalData(oid);
if (personalData == null) {
throw new APIException(APIExceptionType.EXAMINER_ONR_NOT_FOUND);
}

auditService.logById(VktOperation.GET_EXAMINER_INITIAL_DETAILS, oid);

return ExaminerDetailsInitDTO
.builder()
.oid(oid)
Expand All @@ -60,21 +63,19 @@ public ExaminerDetailsInitDTO getInitialExaminerPersonalData(final String oid) {
@Transactional
public ExaminerDetailsDTO upsertExaminer(final String oid, ExaminerDetailsUpsertDTO examinerDetailsUpsertDTO) {
// TODO Audit log entry
Optional<Examiner> existing = examinerRepository.findByOid(oid);
Examiner examiner;
if (existing.isPresent()) {
examiner = existing.get();
} else {
examiner = new Examiner();
examiner.setOid(oid);
PersonalData personalData = this.getOnrPersonalData(oid);
if (personalData == null) {
throw new APIException(APIExceptionType.EXAMINER_ONR_NOT_FOUND);
}
examiner.setLastName(personalData.getLastName());
examiner.setFirstName(personalData.getFirstName());
examiner.setNickname(personalData.getNickname());
final Optional<Examiner> existing = examinerRepository.findByOid(oid);
final Examiner examiner = existing.orElse(new Examiner());

examiner.setOid(oid);

final PersonalData personalData = this.getOnrPersonalData(oid);
if (personalData == null) {
throw new APIException(APIExceptionType.EXAMINER_ONR_NOT_FOUND);
}

examiner.setLastName(personalData.getLastName());
examiner.setFirstName(personalData.getFirstName());
examiner.setNickname(personalData.getNickname());
examiner.setEmail(examinerDetailsUpsertDTO.email());
examiner.setPhoneNumber(examinerDetailsUpsertDTO.phoneNumber());
examiner.setMunicipalities(
Expand All @@ -95,15 +96,16 @@ public ExaminerDetailsDTO upsertExaminer(final String oid, ExaminerDetailsUpsert

@Transactional(readOnly = true)
public ExaminerDetailsDTO getExaminer(final String oid) {
// TODO Audit log entry
final Examiner examiner = examinerRepository.getByOid(oid);
if (examiner == null) {
throw new APIException(APIExceptionType.EXAMINER_NOT_FOUND);
}

auditService.logById(VktOperation.LIST_EXAMINER_DETAILS, oid);

final String baseUrlAPI = environment.getRequiredProperty("app.base-url.api");
final List<EnrollmentAppointment> enrollmentAppointments = enrollmentAppointmentRepository.findByExaminerAndStatusAndDeletedAtIsNull(
examiner,
EnrollmentAppointmentStatus.CONTACT_CREATED
final List<EnrollmentAppointment> enrollmentAppointments = enrollmentAppointmentRepository.findExaminerContactRequests(
examiner
);

return ExaminerUtil.toExaminerDetailsDTO(examiner, enrollmentAppointments, baseUrlAPI);
Expand All @@ -114,7 +116,7 @@ public void updateStoredPersonalData() {
final List<String> onrIds = examinerRepository.listExistingOnrIds();
final Map<String, PersonalData> oidToPersonalData = onrService.getOnrPersonalData(onrIds);
oidToPersonalData.forEach((k, v) -> {
Examiner examiner = examinerRepository.getByOid(k);
final Examiner examiner = examinerRepository.getByOid(k);
examiner.setLastName(v.getLastName());
examiner.setFirstName(v.getFirstName());
examiner.setNickname(v.getNickname());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
package fi.oph.vkt.service;

import fi.oph.vkt.api.dto.EnrollmentGradeDTO;
import fi.oph.vkt.api.dto.clerk.ClerkEnrollmentContactRequestDTO;
import fi.oph.vkt.api.dto.examiner.ExaminerEnrollmentAppointmentDTO;
import fi.oph.vkt.api.dto.examiner.ExaminerEnrollmentAppointmentHistoryDTO;
import fi.oph.vkt.api.dto.examiner.ExaminerEnrollmentAppointmentUpdateDTO;
import fi.oph.vkt.api.dto.examiner.ExaminerEnrollmentGradesDTO;
import fi.oph.vkt.audit.AuditService;
import fi.oph.vkt.audit.VktOperation;
import fi.oph.vkt.model.EnrollmentAppointment;
import fi.oph.vkt.model.EnrollmentGrade;
import fi.oph.vkt.model.ExaminerExamEvent;
import fi.oph.vkt.model.Person;
import fi.oph.vkt.model.type.EnrollmentAppointmentStatus;
import fi.oph.vkt.model.type.EnrollmentGradeType;
import fi.oph.vkt.repository.EnrollmentAppointmentRepository;
import fi.oph.vkt.repository.EnrollmentGradesRepository;
import fi.oph.vkt.repository.ExaminerExamEventRepository;
Expand Down Expand Up @@ -40,6 +40,7 @@ public class ExaminerEnrollmentService extends AbstractEnrollmentService {
private final Environment environment;
private final UUIDSource uuidSource;
private final ExaminerEnrollmentEmailService examinerEnrollmentEmailService;
private final AuditService auditService;

private static void checkExaminerOid(EnrollmentAppointment enrollmentAppointment, String oid) {
if (!enrollmentAppointment.getExaminer().getOid().equals(oid)) {
Expand All @@ -53,6 +54,7 @@ public ExaminerEnrollmentAppointmentDTO updateAppointment(
final Long id,
final ExaminerEnrollmentAppointmentUpdateDTO dto
) {
// TODO Audit log entry
if (!Objects.equals(id, dto.id())) {
throw new APIException(APIExceptionType.EXAMINER_APPOINTMENT_ID_MISMATCH);
}
Expand Down Expand Up @@ -83,6 +85,8 @@ public ClerkEnrollmentContactRequestDTO getEnrollmentContactRequest(
);
checkExaminerOid(enrollmentAppointment, oid);

auditService.logById(VktOperation.VIEW_EXAMINER_CONTACT_REQUEST, enrollmentContactId);

return ClerkEnrollmentUtil.createClerkEnrollmentContactDTO(enrollmentAppointment);
}

Expand All @@ -95,7 +99,7 @@ public ExaminerEnrollmentAppointmentDTO convertToAppointment(final String oid, f

final String baseUrlAPI = environment.getRequiredProperty("app.base-url.api");

enrollmentAppointment.setStatus(EnrollmentAppointmentStatus.WAITING_AUTHENTICATION);
enrollmentAppointment.setStatus(EnrollmentAppointmentStatus.ENROLLMENT_CREATED);

if (enrollmentAppointment.getAuthHash() == null) {
enrollmentAppointment.setAuthHash(uuidSource.getRandomNonce());
Expand Down Expand Up @@ -134,6 +138,8 @@ public ExaminerEnrollmentAppointmentDTO getEnrollmentAppointment(

checkExaminerOid(enrollmentAppointment, oid);

auditService.logById(VktOperation.VIEW_EXAMINER_ENROLLMENT, enrollmentAppointmentId);

final String baseUrlAPI = environment.getRequiredProperty("app.base-url.api");

return ClerkEnrollmentUtil.createClerkEnrollmentAppointmentDTO(enrollmentAppointment, baseUrlAPI);
Expand Down Expand Up @@ -211,6 +217,7 @@ public ExaminerEnrollmentAppointmentDTO sendEnrollmentAppointmentLink(

enrollmentAppointment.setExpiresAt(LocalDateTime.now().plusDays(3));
enrollmentAppointment.setSentAt(LocalDateTime.now());
enrollmentAppointment.setStatus(EnrollmentAppointmentStatus.WAITING_AUTHENTICATION);

examinerEnrollmentEmailService.sendEnrollmentAppointmentAuthLink(enrollmentAppointment);

Expand All @@ -227,6 +234,8 @@ public void deleteEnrollmentContactRequest(final String oid, final long enrollme

checkExaminerOid(enrollmentAppointment, oid);

auditService.logById(VktOperation.DELETE_EXAMINER_CONTACT_REQUEST, enrollmentContactId);

enrollmentAppointment.setDeletedAt(LocalDateTime.now());

enrollmentAppointmentRepository.flush();
Expand Down Expand Up @@ -261,7 +270,9 @@ public List<ExaminerEnrollmentAppointmentHistoryDTO> getEnrollmentAppointmentHis
return List.of();
}

final List<EnrollmentAppointment> enrollmentAppointments = enrollmentAppointmentRepository.findByPersonAndDeletedAtIsNull(
auditService.logById(VktOperation.VIEW_EXAMINER_ENROLLMENT_HISTORY, enrollmentAppointmentId);

final List<EnrollmentAppointment> enrollmentAppointments = enrollmentAppointmentRepository.findPersonEnrollmentHistory(
person
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -402,7 +402,7 @@ export const ClerkEnrollmentAppointmentDetailsFields = ({
const displayPaymentInformation =
[
EnrollmentAppointmentStatus.COMPLETED,
EnrollmentAppointmentStatus.EXPECTING_PAYMENT_UNFINISHED_ENROLLMENT,
EnrollmentAppointmentStatus.AWAITING_PAYMENT,
].includes(enrollment.status) || enrollment.payments.length > 0;

const displayPaymentHistory = enrollment.payments.length > 1;
Expand Down
Loading

0 comments on commit 145079d

Please sign in to comment.