Skip to content

Commit

Permalink
VKT(Frontend & Backend): More emails and various fixes to examiner en…
Browse files Browse the repository at this point in the history
…rollment functions [deploy]
  • Loading branch information
jrkkp committed Nov 19, 2024
1 parent 311ed6e commit b85f842
Show file tree
Hide file tree
Showing 22 changed files with 284 additions and 19 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ public List<PublicExaminerDTO> listExaminers() {
public void createEnrollmentContact(
@RequestBody @Valid final PublicEnrollmentContactCreateDTO dto,
@PathVariable final long examinerId
) {
) throws IOException, InterruptedException {
publicEnrollmentService.createEnrollmentContact(dto, examinerId);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@
import lombok.NonNull;

@Builder
public record PublicExaminerNameDTO(@NonNull @NotNull String lastName, @NonNull @NotNull String firstName) {}
public record PublicExaminerNameDTO(@NonNull @NotNull String name) {}
2 changes: 2 additions & 0 deletions backend/vkt/src/main/java/fi/oph/vkt/model/EmailType.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,6 @@ public enum EmailType {
ENROLLMENT_CONFIRMATION,
ENROLLMENT_TO_QUEUE_CONFIRMATION,
ENROLLMENT_APPOINTMENT_AUTH_LINK,
ENROLLMENT_CONTACT_REQUEST,
ENROLLMENT_APPOINTMENT_CONFIRMATION,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package fi.oph.vkt.service;

import static fi.oph.vkt.util.LocalisationUtil.localeFI;
import static fi.oph.vkt.util.LocalisationUtil.localeSV;

import fi.oph.vkt.model.EmailType;
import fi.oph.vkt.model.EnrollmentAppointment;
import fi.oph.vkt.model.Examiner;
import fi.oph.vkt.service.email.EmailService;
import fi.oph.vkt.util.LocalisationUtil;
import fi.oph.vkt.util.TemplateRenderer;
import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import lombok.RequiredArgsConstructor;
import org.springframework.core.env.Environment;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Service
@RequiredArgsConstructor
public class ContactEmailService extends AbstractEnrollmentEmailService {

private final EmailService emailService;
private final TemplateRenderer templateRenderer;

@Transactional
public void sendEnrollmentAppointmentAuthLink(final EnrollmentAppointment enrollment)
throws IOException, InterruptedException {
final Map<String, Object> templateParams = new HashMap<>(Map.of());
final Examiner examiner = enrollment.getExaminer();

templateParams.put("type", "enrollment");

final String recipientName = examiner.getFirstName() + " " + examiner.getLastName();
final String recipientAddress = examiner.getEmail();
final String subject = String.format(
"%s | %s",
LocalisationUtil.translate(localeFI, "subject.contact-request"),
LocalisationUtil.translate(localeSV, "subject.contact-request")
);
final String body = templateRenderer.renderContactRequest(templateParams);

createEmail(
emailService,
recipientName,
recipientAddress,
subject,
body,
List.of(),
EmailType.ENROLLMENT_CONTACT_REQUEST
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -228,7 +228,7 @@ public Payment finalizePayment(final Long paymentId, final Map<String, String> p

// FIXME
if (newStatus == PaymentStatus.OK) {
//publicEnrollmentEmailService.sendEnrollmentConfirmationEmail(enrollmentAppointment);
publicEnrollmentEmailService.sendEnrollmentAppointmentConfirmationEmail(enrollmentAppointment);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import fi.oph.vkt.api.dto.FreeEnrollmentDetails;
import fi.oph.vkt.model.EmailType;
import fi.oph.vkt.model.Enrollment;
import fi.oph.vkt.model.EnrollmentAppointment;
import fi.oph.vkt.model.Person;
import fi.oph.vkt.model.type.FreeEnrollmentSource;
import fi.oph.vkt.service.email.EmailAttachmentData;
Expand Down Expand Up @@ -282,4 +283,31 @@ public Map<String, Object> withFreeEmailParams(

return freeParams;
}

public void sendEnrollmentAppointmentConfirmationEmail(final EnrollmentAppointment enrollmentAppointment) {
final Map<String, Object> templateParams = getEmailParams(
enrollmentAppointment,
enrollmentAppointment.getExaminerExamEvent()
);
final Person person = enrollmentAppointment.getPerson();

final String recipientName = person.getFirstName() + " " + person.getLastName();
final String recipientAddress = enrollmentAppointment.getEmail();
final String subject = String.format(
"%s | %s",
LocalisationUtil.translate(localeFI, "subject.enrollment-appointment-confirmation"),
LocalisationUtil.translate(localeSV, "subject.enrollment-appointment-confirmation")
);
final String body = templateRenderer.renderEnrollmentAppointmentConfirmationEmailBody(templateParams);

createEmail(
emailService,
recipientName,
recipientAddress,
subject,
body,
List.of(),
EmailType.ENROLLMENT_APPOINTMENT_CONFIRMATION
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
import fi.oph.vkt.util.exception.APIException;
import fi.oph.vkt.util.exception.APIExceptionType;
import fi.oph.vkt.util.exception.NotFoundException;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.List;
import java.util.Map;
Expand All @@ -73,6 +74,7 @@ public class PublicEnrollmentService extends AbstractEnrollmentService {
private final UploadedFileAttachmentRepository uploadedFileAttachmentRepository;
private final KoskiService koskiService;
private final ExaminerRepository examinerRepository;
private final ContactEmailService contactEmailService;

@Transactional
public PublicEnrollmentInitialisationDTO initialiseEnrollment(final long examEventId, final Person person) {
Expand Down Expand Up @@ -622,8 +624,7 @@ private PublicEnrollmentAppointmentDTO createEnrollmentAppointmentDTO(
final PublicPersonDTO personDTO = person == null ? null : PersonUtil.createPublicPersonDTO(person);
final PublicExaminerNameDTO examinerNameDTO = PublicExaminerNameDTO
.builder()
.firstName(examiner.getFirstName())
.lastName(examiner.getLastName())
.name(examiner.getNickname() + " " + examiner.getLastName())
.build();
final PublicAppointmentExamDateDTO examDateDTO = PublicAppointmentExamDateDTO
.builder()
Expand Down Expand Up @@ -692,14 +693,18 @@ public PublicEnrollmentAppointmentDTO saveEnrollmentAppointment(
return createEnrollmentAppointmentDTO(enrollmentAppointment);
}

public void createEnrollmentContact(final PublicEnrollmentContactCreateDTO dto, final long examinerId) {
@Transactional
public void createEnrollmentContact(final PublicEnrollmentContactCreateDTO dto, final long examinerId)
throws IOException, InterruptedException {
final EnrollmentAppointment enrollmentAppointment = new EnrollmentAppointment();
final Examiner examiner = examinerRepository.getReferenceById(examinerId);

enrollmentAppointment.setStatus(EnrollmentAppointmentStatus.CONTACT_CREATED);
enrollmentAppointment.setExaminer(examiner);
copyDtoFieldsToEnrollment(enrollmentAppointment, dto);

contactEmailService.sendEnrollmentAppointmentAuthLink(enrollmentAppointment);

enrollmentAppointmentRepository.saveAndFlush(enrollmentAppointment);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,14 @@ public String renderEnrollmentAppointmentAuthLink(final Map<String, Object> para
return renderTemplate("enrollment-appointment-auth-link", params, Optional.empty());
}

public String renderEnrollmentAppointmentConfirmationEmailBody(final Map<String, Object> params) {
return renderTemplate("enrollment-appointment-confirmation", params, Optional.empty());
}

public String renderContactRequest(final Map<String, Object> params) {
return renderTemplate("examiner-contact-request.html", params, Optional.empty());
}

public String renderReceipt(final Locale locale, final Map<String, Object> params) {
return renderTemplate("receipt", params, Optional.of(locale));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1157,4 +1157,12 @@
<column name="name" value="ENROLLMENT_APPOINTMENT_AUTH_LINK"/>
</insert>
</changeSet>
<changeSet id="2024-11-20-add-enrollment-contact-request-email-type" author="jrkkp">
<insert tableName="email_type">
<column name="name" value="ENROLLMENT_CONTACT_REQUEST"/>
</insert>
<insert tableName="email_type">
<column name="name" value="ENROLLMENT_APPOINTMENT_CONFIRMATION"/>
</insert>
</changeSet>
</databaseChangeLog>
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
<!DOCTYPE html>
<html lang="fi" xmlns:th="http://www.thymeleaf.org">
<body>
<p>
Hei,
</p>
<br/>
<p>Olet ilmoittautunut Valtionhallinnon kielitutkintoon. Ohessa tiedot ilmoittautumisestasi. Liitteenä myös maksukuitti suomeksi ja ruotsiksi.</p>
<br/>

<p>
<b>Tutkinnon kieli:</b> <span th:text="${examLanguageFI}"></span><br/>
<b>Tutkinnon taso:</b> <span th:text="${examLevelFI}"></span><br/>
<b>Tutkintopäivä:</b> <span th:text="${examDate}"></span><br/>
<b>Valitsemasi taidot:</b> <span th:text="${skillsFI}"></span><br/>
<b>Valitsemasi osakokeet:</b> <span th:text="${partialExamsFI}"></span><br/>
</p>
<br/>

<p><b>Tietoa tutkintotilaisuudesta</b></p>

<p>Tutkintotilaisuus järjestetään Opetushallituksen tiloissa osoitteessa Hakaniemenranta 6, 00530 Helsinki.</p>
<p>Tutkinnon suorittamiseen kannattaa varata koko päivä. Tutkintotilaisuus alkaa klo 9.00 kirjallisen taidon tutkinnolla ja jatkuu iltapäivällä suullisen taidon tutkinnolla. Tutkinnon päättymisaika riippuu tutkintoon osallistuvien määrästä. Saat tarkemmat ohjeet tutkintopäivän kulusta viikkoa ennen tutkintopäivää.</p>
<p>Jos sinulla on kysyttävää tutkinnosta, voit lähettää meille sähköpostia osoitteeseen <a href="mailto:[email protected]">[email protected]</a>. Ilmoitathan viipymättä, jos et pysty osallistumaan tutkintoon.</p>
<p>
Lisätietoa tutkinnosta löydät Opetushallituksen verkkopalvelusta:<br/>
<a href="https://www.oph.fi/fi/koulutus-ja-tutkinnot/erinomaisen-taidon-tutkinnot" target="_blank">Valtionhallinnon kielitutkinnot (VKT)</a>
</p>
<br/>

<p>
Älä vastaa tähän viestiin - viesti on lähetetty automaattisesti.
</p>
<p style="border-bottom: 1px solid black; padding-bottom: 15px;">
Ystävällisin terveisin<br/>
Opetushallitus
</p>

<p>
Hej,
</p>
<br/>
<p>Du har anmält dig till Språkexamen för statsförvaltningen (VKT). Uppgifter om din anmälan hittar du nedan. Bifogat finns även kvittot för din examensavgift på finska och på svenska.</p>
<br/>

<p>
<b>Examensspråk:</b> <span th:text="${examLanguageSV}"></span><br/>
<b>Examensnivå:</b> <span th:text="${examLevelSV}"></span><br/>
<b>Examensdatum:</b> <span th:text="${examDate}"></span><br/>
<b>Förmågor som du har valt:</b> <span th:text="${skillsSV}"></span><br/>
<b>Delprov som du har valt:</b> <span th:text="${partialExamsSV}"></span><br/>
</p>
<br/>
<p><b>Information om examenstillfället</b></p>

<p>Examenstillfället ordnas vid Utbildningsstyrelsen på adressen Hagnäskajen 6, 00530 Helsingfors.</p>
<p>Du bör reservera hela dagen för examen. Examenstillfället börjar klockan 9.00 med delprovet i skriftlig färdighet och fortsätter på eftermiddagen med delprovet i muntlig färdighet. Deltagarantalet avgör när examenstillfället slutar. Du får närmare anvisningar om examensdagens program en vecka före examensdagen.</p>
<p>Om du har frågor om examen, kan du kontakta oss per e-post på adressen <a href="mailto:[email protected]">[email protected]</a>. Vänligen meddela omedelbart om du inte kan delta i examen.</p>
<p>
Närmare information om examen finns på Utbildningsstyrelsens webbplats:<br/>
<a href="https://www.oph.fi/sv/utbildning-och-examina/examina-som-galler-utmarkta-sprakkunskaper" target="_blank">Språkexamina för statsförvaltningen (VKT)</a>
</p>
<br/>

<p>
Svara inte på detta meddelande, det har skickats automatiskt.
</p>
<p>
Med vänlig hälsning<br/>
Utbildningsstyrelsen
</p>
</body>
</html>
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!DOCTYPE html>
<html lang="fi" xmlns:th="http://www.thymeleaf.org">
<body>
<p>
Hei,
</p>

<p>Olet saanut yhteydenottopyynnön.</p>
<br/>
<p>Tarkastele yhteydenottopyynnön tietoja VKT palvelussa.</p>

<p>
Älä vastaa tähän viestiin - viesti on lähetetty automaattisesti.
</p>
<p style="border-bottom: 1px solid black; padding-bottom: 15px;">
Ystävällisin terveisin<br/>
Opetushallitus
</p>

</body>
</html>
2 changes: 2 additions & 0 deletions backend/vkt/src/main/resources/localisation_fi.properties
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ skill.mail.textual = Kirjallinen taito
skill.mail.oral = Suullinen taito
subject.enrollment-confirmation = Vahvistus ilmoittautumisesta Valtionhallinnon kielitutkintoon (VKT)
subject.enrollment-to-queue-confirmation = Vahvistus ilmoittautumisesta jonotuspaikalle Valtionhallinnon kielitutkintoon (VKT)
subject.enrollment-appointment-confirmation = Vahvistus ilmoittautumisesta Valtionhallinnon kielitutkintoon (VKT)
subject.contact-request = Yhteydenotto Valtionhallinnon kielitutkintoon (VKT)
2 changes: 2 additions & 0 deletions backend/vkt/src/main/resources/localisation_sv.properties
Original file line number Diff line number Diff line change
Expand Up @@ -27,3 +27,5 @@ skill.mail.textual = Förmåga att använda språket i skrift
skill.mail.oral = Förmåga att använda språket i tal
subject.enrollment-confirmation = Bekräftelse av anmälan till Språkexamen för statsförvaltningen (VKT)
subject.enrollment-to-queue-confirmation = Bekräftelse av plats i kön för Språkexamen för statsförvaltningen (VKT)
subject.enrollment-appointment-confirmation = Bekräftelse av anmälan till Språkexamen för statsförvaltningen (VKT)
subject.contact-request = Yhteydenotto Valtionhallinnon kielitutkintoon (VKT)
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,9 @@ public class PublicEnrollmentServiceTest {
@Resource
private ExaminerRepository examinerRepository;

@Resource
private ContactEmailService contactEmailService;

@BeforeEach
public void setup() throws IOException, InterruptedException {
doNothing().when(publicEnrollmentEmailServiceMock).sendEnrollmentToQueueConfirmationEmail(any(), any());
Expand Down Expand Up @@ -121,7 +124,8 @@ public void setup() throws IOException, InterruptedException {
featureFlagService,
uploadedFileAttachmentRepository,
koskiService,
examinerRepository
examinerRepository,
contactEmailService
);
}

Expand Down
4 changes: 4 additions & 0 deletions frontend/packages/vkt/public/i18n/fi-FI/clerk.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@
"description": "Tätä toimintoa ei voi peruuttaa!",
"header": "Haluatko varmasti peruuttaa ilmoittautumisen?"
},
"authLinkErrorDialog": {
"description": "Ilmoittautuja täytyy liittää tutkintoon ennen ilmoittautumislinkin lähetystä.",
"header": "Valitse tutkinto"
},
"controlButtons": {
"move": "Siirrä"
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -107,8 +107,7 @@ export const ClerkEnrollmentAppointmentDetails = ({
const hasRequiredDetails =
StringUtils.isNonBlankString(enrollmentDetails.email) &&
StringUtils.isNonBlankString(enrollmentDetails.phoneNumber) &&
EnrollmentUtils.isValidPartialExamsAndSkills(enrollmentDetails) &&
EnrollmentUtils.isValidCertificateShipping(enrollmentDetails);
EnrollmentUtils.isValidPartialExamsAndSkills(enrollmentDetails);

const handleTextFieldChange =
(field: ClerkEnrollmentTextFieldEnum) =>
Expand Down
Loading

0 comments on commit b85f842

Please sign in to comment.