From bb365162bc8e93b9364267409610c90f52c5805f Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Vicen=C3=ADkov=C3=A1=20Jitka?=
 <Jitka.Vicenikova@partners.cz>
Date: Sun, 23 Apr 2023 10:19:25 +0200
Subject: [PATCH] application notifications

---
 application/openapi.yaml                      |  2 +
 .../pa165/service/ApplicationService.java     | 16 ++++
 .../pa165/service/CarComponentService.java    | 27 +++---
 notification/openapi.yaml                     | 91 ++++++++++++++++++-
 .../muni/pa165/facade/NotificationFacade.java | 18 +++-
 .../pa165/rest/NotificationController.java    | 23 +++--
 .../pa165/service/NotificationService.java    | 68 ++++++++++++--
 7 files changed, 211 insertions(+), 34 deletions(-)

diff --git a/application/openapi.yaml b/application/openapi.yaml
index 76f3b1a..36bdf25 100644
--- a/application/openapi.yaml
+++ b/application/openapi.yaml
@@ -27,6 +27,7 @@ components:
         - name
         - surname
         - fillingOutDate
+        - email
       properties:
         id:
           type: integer
@@ -76,6 +77,7 @@ components:
       required:
         - name
         - surname
+        - email
 
   responses:
     NotFound:
diff --git a/application/src/main/java/cz/muni/pa165/service/ApplicationService.java b/application/src/main/java/cz/muni/pa165/service/ApplicationService.java
index e3d4925..bdb6555 100644
--- a/application/src/main/java/cz/muni/pa165/service/ApplicationService.java
+++ b/application/src/main/java/cz/muni/pa165/service/ApplicationService.java
@@ -5,11 +5,16 @@ import cz.muni.pa165.data.model.Application;
 import cz.muni.pa165.data.repository.ApplicationRepository;
 import cz.muni.pa165.exceptions.ResourceNotFoundException;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpHeaders;
+import org.springframework.http.MediaType;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
 import java.time.LocalDate;
+import java.util.HashMap;
 import java.util.List;
+import java.util.Map;
 import java.util.Optional;
 
 /**
@@ -53,4 +58,15 @@ public class ApplicationService {
 
         return applicationRepository.save(applicationFromDb.get());
     }
+
+   /* private void sendNewApplicationPostRequest(Application application) {
+        Map<String, Object> notification = new HashMap<>();
+        notification.put("carComponent", component);
+        notification.put("receivers", NOTIFICATION_RECEIVERS);
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        HttpEntity<Map<String, Object>> request = new HttpEntity<>(notification, headers);
+        restTemplate.postForObject(NOTIFICATION_MODULE_URL, request, String.class);
+    }*/
 }
diff --git a/core/src/main/java/cz/muni/pa165/service/CarComponentService.java b/core/src/main/java/cz/muni/pa165/service/CarComponentService.java
index 4e7405e..dd8eaab 100644
--- a/core/src/main/java/cz/muni/pa165/service/CarComponentService.java
+++ b/core/src/main/java/cz/muni/pa165/service/CarComponentService.java
@@ -23,7 +23,9 @@ public class CarComponentService extends DomainService<CarComponent> {
     private final CarComponentRepository componentRepository;
     private final RestTemplate restTemplate;
 
-    private final String NOTIFICATION_MODULE_URL = "http://localhost:8083/notification";
+    private static final String NOTIFICATION_MODULE_URL = "http://localhost:8083/notification/component";
+    private static final List<String> NOTIFICATION_RECEIVERS = List.of("jitka.vicenikova@gmail.com");
+
     @Autowired
     public CarComponentService(CarComponentRepository repository, RestTemplate restTemplate) {
         super(repository, CarComponent.class);
@@ -41,18 +43,6 @@ public class CarComponentService extends DomainService<CarComponent> {
         return savedComponent;
     }
 
-    private void sendPostRequest(CarComponent component) {
-        Map<String, Object> notification = new HashMap<>();
-        notification.put("subject", "New CarComponent added");
-        notification.put("message", "A new CarComponent with ID " + component.getId() + " has been added.");
-        notification.put("receivers", Collections.singletonList(Collections.singletonMap("emailAddress", "manager@example.com")));
-
-        HttpHeaders headers = new HttpHeaders();
-        headers.setContentType(MediaType.APPLICATION_JSON);
-        HttpEntity<Map<String, Object>> request = new HttpEntity<>(notification, headers);
-        restTemplate.postForObject(NOTIFICATION_MODULE_URL, request, String.class);
-    }
-
     public CarComponent update(Long id, CarComponent component) {
         Optional<CarComponent> dbComponent = componentRepository.findById(id);
         if (dbComponent.isEmpty()) {
@@ -76,4 +66,15 @@ public class CarComponentService extends DomainService<CarComponent> {
     public List<CarComponent> findAllByType(ComponentTypeEnum type) {
         return componentRepository.findByType(type);
     }
+
+    private void sendPostRequest(CarComponent component) {
+        Map<String, Object> notification = new HashMap<>();
+        notification.put("carComponent", component);
+        notification.put("receivers", NOTIFICATION_RECEIVERS);
+
+        HttpHeaders headers = new HttpHeaders();
+        headers.setContentType(MediaType.APPLICATION_JSON);
+        HttpEntity<Map<String, Object>> request = new HttpEntity<>(notification, headers);
+        restTemplate.postForObject(NOTIFICATION_MODULE_URL, request, String.class);
+    }
 }
diff --git a/notification/openapi.yaml b/notification/openapi.yaml
index 1ee8078..77a138b 100644
--- a/notification/openapi.yaml
+++ b/notification/openapi.yaml
@@ -45,6 +45,21 @@ components:
           items:
             type: string
           description: Email addresses the notification is sent to
+    ApplicationNotificationDto:
+      type: object
+      title: ApplicationNotification
+      description: Notification about new component to be send to receivers
+      required:
+        - application
+        - receivers
+      properties:
+        application:
+          $ref: "#/components/schemas/ApplicationDto"
+        receivers:
+          type: array
+          items:
+            type: string
+          description: Email addresses the notification is sent to
     ConfirmationDto:
       type: object
       title: Confirmation
@@ -95,6 +110,54 @@ components:
           type: string
           description: Specific information about component
           example: lightweight front wing v2 (black)
+
+    ApplicationStatus:
+      type: string
+      description: Status of application
+      enum:
+        - pending
+        - rejected
+        - accepted
+
+    ApplicationDto:
+      type: object
+      title: Application
+      description: Application for becoming driver
+      required:
+        - id
+        - name
+        - surname
+        - fillingOutDate
+        - email
+      properties:
+        id:
+          type: integer
+          description: Id of the application
+          example: 1
+          format: int64
+        name:
+          type: string
+          description: Name of the person
+          example: Max
+        surname:
+          type: string
+          description: Surname of the person
+          example: Verstappen
+        birthday:
+          type: string
+          description: Date of birth
+          example: 09-30-1997
+          format: date
+        email:
+          type: string
+          description: Email address of the person
+        fillingOutDate:
+          type: string
+          description: Date of filling out the application
+          example: 09-30-1997
+          format: date
+        status:
+          $ref: '#/components/schemas/ApplicationStatus'
   responses:
     Unexpected:
       description: Unexpected error
@@ -135,7 +198,7 @@ paths:
       tags:
         - NotificationService
       summary: Creates and sends notification(s) about new component
-      operationId: notifyComponentChange
+      operationId: notifyNewComponent
       requestBody:
         required: true
         description: Request body with receiver and car component for new notification
@@ -152,7 +215,7 @@ paths:
                 $ref: '#/components/schemas/ConfirmationDto'
         default:
           $ref: '#/components/responses/Unexpected'
-  /notification/application:
+  /notification/application/new:
     post:
       tags:
         - NotificationService
@@ -164,7 +227,29 @@ paths:
         content:
           application/json:
             schema:
-              $ref: '#/components/schemas/NotificationDto'
+              $ref: '#/components/schemas/ApplicationNotificationDto'
+      responses:
+        "200":
+          description: OK
+          content:
+            application/json:
+              schema:
+                $ref: '#/components/schemas/ConfirmationDto'
+        default:
+          $ref: '#/components/responses/Unexpected'
+  /notification/application/status:
+    post:
+      tags:
+        - NotificationService
+      summary: Creates and sends notification
+      operationId: notifyApplicationStatusChange
+      requestBody:
+        required: true
+        description: Request body with receiver and message for new notification
+        content:
+          application/json:
+            schema:
+              $ref: '#/components/schemas/ApplicationNotificationDto'
       responses:
         "200":
           description: OK
diff --git a/notification/src/main/java/cz/muni/pa165/facade/NotificationFacade.java b/notification/src/main/java/cz/muni/pa165/facade/NotificationFacade.java
index 0479a0b..95ef618 100644
--- a/notification/src/main/java/cz/muni/pa165/facade/NotificationFacade.java
+++ b/notification/src/main/java/cz/muni/pa165/facade/NotificationFacade.java
@@ -1,10 +1,9 @@
 package cz.muni.pa165.facade;
 
-import cz.muni.pa165.generated.model.CarComponentNotificationDto;
-import cz.muni.pa165.generated.model.ConfirmationDto;
-import cz.muni.pa165.generated.model.NotificationDto;
+import cz.muni.pa165.generated.model.*;
 import cz.muni.pa165.service.NotificationService;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.ResponseEntity;
 import org.springframework.stereotype.Service;
 
 @Service
@@ -22,7 +21,16 @@ public class NotificationFacade {
         return notificationService.notify(notificationDto);
     }
 
-    public ConfirmationDto notifyComponentChange(CarComponentNotificationDto carComponentNotificationDto) {
-        return notificationService.notifyComponentChange(carComponentNotificationDto);
+    public ConfirmationDto notifyNewComponent(CarComponentNotificationDto carComponentNotificationDto) {
+        return notificationService.notifyNewComponent(carComponentNotificationDto);
+    }
+
+    public ConfirmationDto notifyNewApplication(ApplicationNotificationDto applicationDto) {
+        return notificationService.notifyNewApplication(applicationDto);
+    }
+
+    public ConfirmationDto notifyApplicationStatusChange(ApplicationNotificationDto applicationDto) {
+        return notificationService.notifyApplicationStatusChange(applicationDto);
+
     }
 }
diff --git a/notification/src/main/java/cz/muni/pa165/rest/NotificationController.java b/notification/src/main/java/cz/muni/pa165/rest/NotificationController.java
index 4bdfb06..e27025a 100644
--- a/notification/src/main/java/cz/muni/pa165/rest/NotificationController.java
+++ b/notification/src/main/java/cz/muni/pa165/rest/NotificationController.java
@@ -2,9 +2,7 @@ package cz.muni.pa165.rest;
 
 import cz.muni.pa165.facade.NotificationFacade;
 import cz.muni.pa165.generated.api.NotificationServiceApiDelegate;
-import cz.muni.pa165.generated.model.CarComponentNotificationDto;
-import cz.muni.pa165.generated.model.ConfirmationDto;
-import cz.muni.pa165.generated.model.NotificationDto;
+import cz.muni.pa165.generated.model.*;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -35,10 +33,23 @@ public class NotificationController implements NotificationServiceApiDelegate {
     }
 
     @Override
-    public ResponseEntity<ConfirmationDto> notifyComponentChange(
-            CarComponentNotificationDto carComponentNotificationDto) {
+    public ResponseEntity<ConfirmationDto> notifyNewComponent(CarComponentNotificationDto carComponentNotificationDto) {
         log.debug("notifyComponentChange() called");
 
-        return new ResponseEntity<>(notificationFacade.notifyComponentChange(carComponentNotificationDto), HttpStatus.OK);
+        return new ResponseEntity<>(notificationFacade.notifyNewComponent(carComponentNotificationDto), HttpStatus.OK);
+    }
+
+    @Override
+    public ResponseEntity<ConfirmationDto> notifyNewApplication(ApplicationNotificationDto applicationDto) {
+        log.debug("notifyNewApplication() called");
+
+        return new ResponseEntity<>(notificationFacade.notifyNewApplication(applicationDto), HttpStatus.OK);
+    }
+
+    @Override
+    public ResponseEntity<ConfirmationDto> notifyApplicationStatusChange(ApplicationNotificationDto applicationDto) {
+        log.debug("notifyApplicationStatusChange() called");
+
+        return new ResponseEntity<>(notificationFacade.notifyApplicationStatusChange(applicationDto), HttpStatus.OK);
     }
 }
diff --git a/notification/src/main/java/cz/muni/pa165/service/NotificationService.java b/notification/src/main/java/cz/muni/pa165/service/NotificationService.java
index dfc3769..444378a 100644
--- a/notification/src/main/java/cz/muni/pa165/service/NotificationService.java
+++ b/notification/src/main/java/cz/muni/pa165/service/NotificationService.java
@@ -1,8 +1,6 @@
 package cz.muni.pa165.service;
 
-import cz.muni.pa165.generated.model.CarComponentNotificationDto;
-import cz.muni.pa165.generated.model.ConfirmationDto;
-import cz.muni.pa165.generated.model.NotificationDto;
+import cz.muni.pa165.generated.model.*;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.mail.SimpleMailMessage;
 import org.springframework.mail.javamail.JavaMailSender;
@@ -21,10 +19,10 @@ public class NotificationService {
     }
 
     public ConfirmationDto notify(NotificationDto notificationDto) {
-        return sendMail(notificationDto.getSubject(), notificationDto.getMessage(), notificationDto.getReceivers());
+        return sendEmail(notificationDto.getSubject(), notificationDto.getMessage(), notificationDto.getReceivers());
     }
 
-    public ConfirmationDto notifyComponentChange(CarComponentNotificationDto carComponentNotificationDto) {
+    public ConfirmationDto notifyNewComponent(CarComponentNotificationDto carComponentNotificationDto) {
         var c = carComponentNotificationDto.getCarComponent();
         var subject = "New component: " + c.getInformation();
         var text = "New component was added to Formula team management core.\n"
@@ -32,10 +30,62 @@ public class NotificationService {
                 + "\nInformation: " + c.getInformation()
                 + "\nWeight: " + c.getWeight();
 
-        return sendMail(subject, text, carComponentNotificationDto.getReceivers());
+        return sendEmail(subject, text, carComponentNotificationDto.getReceivers());
     }
 
-    private ConfirmationDto sendMail(String subject, String content, List<String> receivers) {
+    public ConfirmationDto notifyNewApplication(ApplicationNotificationDto applicationNotificationDto) {
+        var a = applicationNotificationDto.getApplication();
+        var subject = "New application: " + getFullName(a);
+        var text = "New application was received.\n"
+                + "\nId: " + a.getId()
+                + "\nName: " + a.getName()
+                + "\nSurname: " + a.getSurname()
+                + "\nBirthday: " + a.getBirthday()
+                + "\nEmail: " + a.getEmail()
+                + "\nFilling out date: " + a.getFillingOutDate();
+
+
+        return sendEmail(subject, text, applicationNotificationDto.getReceivers());
+    }
+
+    public ConfirmationDto notifyApplicationStatusChange(ApplicationNotificationDto applicationNotificationDto) {
+        var a = applicationNotificationDto.getApplication();
+        var subject = "Application for Formula Driver Position";
+        var text = "";
+        if (a.getStatus() == ApplicationStatus.ACCEPTED) {
+            text = "Dear " + getFullName(a) + ",\n" +
+                    "\n" +
+                    "I am pleased to inform you that your application for the position of Formula Driver has been accepted. We are excited to have you join our team and look forward to working with you.\n" +
+                    "\n" +
+                    "Your experience, skills, and passion for racing make you an excellent fit for our team. We believe that you will be a valuable asset to our organization and we are eager to see what you can accomplish on the track.\n" +
+                    "\n" +
+                    "As a next step, we will contact you shortly to discuss the details of your employment contract and to schedule your training and orientation. In the meantime, please do not hesitate to contact us if you have any questions or concerns.\n" +
+                    "\n" +
+                    "Thank you for your interest in our team and for taking the time to apply. We look forward to a long and successful partnership with you.\n" +
+                    "\n" +
+                    "Best regards,\n" +
+                    "\n" +
+                    "Formula Team Management";
+        } else {
+            text = "Dear " + getFullName(a) + ",\n" +
+                    "\n" +
+                    "I regret to inform you that your application for the Formula Driver position has been declined. While we appreciate your interest in the role, we have decided to pursue other candidates whose skills and experience more closely match our requirements.\n" +
+                    "\n" +
+                    "I want to personally thank you for taking the time to apply for the position and for your passion for motorsports. We would like to keep your resume on file in case any suitable openings arise in the future.\n" +
+                    "\n" +
+                    "If you have any questions or would like feedback on your application, please feel free to reach out to us.\n" +
+                    "\n" +
+                    "Thank you again for considering Formula Team Management, and we wish you all the best in your future endeavors.\n" +
+                    "\n" +
+                    "Best regards,\n" +
+                    "\n" +
+                    "Formula Team Management";
+        }
+
+        return sendEmail(subject, text, applicationNotificationDto.getReceivers());
+    }
+
+    private ConfirmationDto sendEmail(String subject, String content, List<String> receivers) {
         var message = new SimpleMailMessage();
 
         message.setFrom(EMAIL);
@@ -50,4 +100,8 @@ public class NotificationService {
                 .subject(subject)
                 .message(content);
     }
+
+    private String getFullName(ApplicationDto applicationDto) {
+        return applicationDto.getName() + " " + applicationDto.getSurname();
+    }
 }
-- 
GitLab