Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Préavis – Afficher la liste de diffusion (unités et leurs contacts) dans les préavis et si la diffusion a réussi ou non #3669

Draft
wants to merge 6 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package fr.gouv.cnsp.monitorfish.domain.entities.prior_notification

import java.time.ZonedDateTime

data class PriorNotificationSentMessage(
val id: Int,
val communicationMeans: String,
val dateTimeUtc: ZonedDateTime,
val errorMessage: String?,
val priorNotificationReportId: String?,
val priorNotificationSource: String,
val recipientAddressOrNumber: String,
val success: Boolean,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
package fr.gouv.cnsp.monitorfish.domain.repositories

import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage

interface PriorNotificationSentMessageRepository {
fun findAllByReportId(reportId: String): List<PriorNotificationSentMessage>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package fr.gouv.cnsp.monitorfish.domain.use_cases.prior_notification

import fr.gouv.cnsp.monitorfish.config.UseCase
import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage
import fr.gouv.cnsp.monitorfish.domain.repositories.*

@UseCase
class GetPriorNotificationSentMessages(
private val priorNotificationSentMessageRepository: PriorNotificationSentMessageRepository,
) {
fun execute(reportId: String): List<PriorNotificationSentMessage> {
return priorNotificationSentMessageRepository.findAllByReportId(reportId)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ class PriorNotificationController(
private val deletePriorNotificationUpload: DeletePriorNotificationUpload,
private val getPriorNotification: GetPriorNotification,
private val getPriorNotificationPdfDocument: GetPriorNotificationPdfDocument,
private val getPriorNotificationSentMessages: GetPriorNotificationSentMessages,
private val getPriorNotificationUpload: GetPriorNotificationUpload,
private val getPriorNotificationUploads: GetPriorNotificationUploads,
private val getPriorNotifications: GetPriorNotifications,
Expand Down Expand Up @@ -374,6 +375,17 @@ class PriorNotificationController(
return PriorNotificationDataOutput.fromPriorNotification(updatedPriorNotification)
}

@GetMapping("/{reportId}/sent_messages")
@Operation(summary = "Get all sent messages for a given prior notification")
fun getSentMessages(
@PathParam("Logbook message `reportId`")
@PathVariable(name = "reportId")
reportId: String,
): List<PriorNotificationSentMessageDataOutput> {
return getPriorNotificationSentMessages.execute(reportId)
.map { PriorNotificationSentMessageDataOutput.fromPriorNotificationSentMessage(it) }
}

@GetMapping("/{reportId}/uploads/{priorNotificationUploadId}")
@Operation(summary = "Download a prior notification attachment")
fun getUploads(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package fr.gouv.cnsp.monitorfish.infrastructure.api.outputs

import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage
import java.time.ZonedDateTime

data class PriorNotificationSentMessageDataOutput(
val id: Int,
val communicationMeans: String,
val dateTimeUtc: ZonedDateTime,
val errorMessage: String?,
val recipientAddressOrNumber: String,
val success: Boolean,
) {
companion object {
fun fromPriorNotificationSentMessage(
priorNotificationSentMessage: PriorNotificationSentMessage,
): PriorNotificationSentMessageDataOutput {
return PriorNotificationSentMessageDataOutput(
id = priorNotificationSentMessage.id,
communicationMeans = priorNotificationSentMessage.communicationMeans,
dateTimeUtc = priorNotificationSentMessage.dateTimeUtc,
errorMessage = priorNotificationSentMessage.errorMessage,
recipientAddressOrNumber = priorNotificationSentMessage.recipientAddressOrNumber,
success = priorNotificationSentMessage.success,
)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package fr.gouv.cnsp.monitorfish.infrastructure.database.entities

import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage
import jakarta.persistence.*
import org.hibernate.annotations.Immutable
import java.time.ZonedDateTime

@Entity
@Immutable
@Table(name = "prior_notification_sent_messages")
data class PriorNotificationSentMessageEntity(
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false)
val id: Int,
@Column(name = "communication_means", nullable = false)
val communicationMeans: String,
@Column(name = "date_time_utc", nullable = false)
val dateTimeUtc: ZonedDateTime,
@Column(name = "error_message", nullable = true)
val errorMessage: String?,
@Column(name = "prior_notification_report_id", nullable = false)
val priorNotificationReportId: String?,
@Column(name = "prior_notification_source", nullable = false)
val priorNotificationSource: String,
@Column(name = "recipient_address_or_number", nullable = false)
val recipientAddressOrNumber: String,
@Column(name = "success", nullable = false)
val success: Boolean,
) {
fun toPriorNotificationSentMessage(): PriorNotificationSentMessage {
return PriorNotificationSentMessage(
id = id,
communicationMeans = communicationMeans,
dateTimeUtc = dateTimeUtc,
errorMessage = errorMessage,
priorNotificationReportId = priorNotificationReportId,
priorNotificationSource = priorNotificationSource,
recipientAddressOrNumber = recipientAddressOrNumber,
success = success,
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fr.gouv.cnsp.monitorfish.infrastructure.database.repositories

import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage
import fr.gouv.cnsp.monitorfish.domain.repositories.PriorNotificationSentMessageRepository
import fr.gouv.cnsp.monitorfish.infrastructure.database.repositories.interfaces.DBPriorNotificationSentMessageRepository
import org.springframework.stereotype.Repository

@Repository
class JpaPriorNotificationSentMessageRepository(
private val dbPriorNotificationSentMessageRepository: DBPriorNotificationSentMessageRepository,
) : PriorNotificationSentMessageRepository {
override fun findAllByReportId(reportId: String): List<PriorNotificationSentMessage> {
return dbPriorNotificationSentMessageRepository
.findAllByReportId(reportId)
.map { it.toPriorNotificationSentMessage() }
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
package fr.gouv.cnsp.monitorfish.infrastructure.database.repositories.interfaces

import fr.gouv.cnsp.monitorfish.infrastructure.database.entities.PriorNotificationSentMessageEntity
import org.springframework.data.jpa.repository.JpaRepository
import org.springframework.data.jpa.repository.Query

interface DBPriorNotificationSentMessageRepository : JpaRepository<PriorNotificationSentMessageEntity, String> {
@Query(
"""
SELECT *
FROM prior_notification_sent_messages
WHERE prior_notification_report_id = :reportId
""",
nativeQuery = true,
)
fun findAllByReportId(reportId: String): List<PriorNotificationSentMessageEntity>
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
INSERT INTO public.prior_notification_sent_messages (
prior_notification_report_id, prior_notification_source, date_time_utc, communication_means, recipient_address_or_number, success, error_message
) VALUES
('FAKE_OPERATION_103', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', TRUE, NULL),
('FAKE_OPERATION_106', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', TRUE, NULL),
('FAKE_OPERATION_106', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', TRUE, NULL),
('FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', FALSE, NULL),
('FAKE_OPERATION_108', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', FALSE, NULL),
('FAKE_OPERATION_110', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', TRUE, NULL),
('FAKE_OPERATION_110', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', FALSE, NULL),
('FAKE_OPERATION_110', 'LOGBOOK', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'SMS', '+33123456789', FALSE, NULL),
('00000000-0000-4000-0000-000000000003', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', TRUE, NULL),
('00000000-0000-4000-0000-000000000003', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', FALSE, NULL),
('00000000-0000-4000-0000-000000000004', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', FALSE, NULL),
('00000000-0000-4000-0000-000000000006', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', TRUE, NULL),
('00000000-0000-4000-0000-000000000008', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', FALSE, NULL),
('00000000-0000-4000-0000-000000000010', 'MANUAL', NOW() AT TIME ZONE 'UTC' - INTERVAL '2 minutes', 'EMAIL', '[email protected]', TRUE, NULL);
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package fr.gouv.cnsp.monitorfish.domain.use_cases.prior_notification

import com.nhaarman.mockitokotlin2.given
import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationSentMessage
import fr.gouv.cnsp.monitorfish.domain.repositories.PriorNotificationSentMessageRepository
import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.junit.jupiter.api.extension.ExtendWith
import org.springframework.boot.test.mock.mockito.MockBean
import org.springframework.test.context.junit.jupiter.SpringExtension
import java.time.ZonedDateTime

@ExtendWith(SpringExtension::class)
class GetPriorNotificationSentMessagesUTests {
@MockBean
private lateinit var priorNotificationSentMessageRepository: PriorNotificationSentMessageRepository

@Test
fun `execute Should return a list of prior notification types`() {
// Given
val fakeReportId = "FAKE_REPORT_ID"
given(priorNotificationSentMessageRepository.findAllByReportId(fakeReportId)).willReturn(
listOf(
PriorNotificationSentMessage(
id = 1,
communicationMeans = "EMAIL",
dateTimeUtc = ZonedDateTime.now(),
errorMessage = null,
priorNotificationReportId = fakeReportId,
priorNotificationSource = "LOGBOOK",
recipientAddressOrNumber = "[email protected]",
success = true,
),
PriorNotificationSentMessage(
id = 2,
communicationMeans = "SMS",
dateTimeUtc = ZonedDateTime.now(),
errorMessage = null,
priorNotificationReportId = fakeReportId,
priorNotificationSource = "MANUAL",
recipientAddressOrNumber = "+33123456789",
success = true,
),
),
)

// When
val result = GetPriorNotificationSentMessages(priorNotificationSentMessageRepository).execute(fakeReportId)

// Then
assertThat(result).hasSize(2)
assertThat(result[0].communicationMeans).isEqualTo("EMAIL")
assertThat(result[1].communicationMeans).isEqualTo("SMS")
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ class PriorNotificationControllerUTests {
@MockBean
private lateinit var getPriorNotificationPdfDocument: GetPriorNotificationPdfDocument

@MockBean
private lateinit var getPriorNotificationSentMessages: GetPriorNotificationSentMessages

@MockBean
private lateinit var getPriorNotificationUpload: GetPriorNotificationUpload

Expand Down Expand Up @@ -497,4 +500,43 @@ class PriorNotificationControllerUTests {
)
.andExpect(jsonPath("$.reportId", equalTo(fakePriorNotification.reportId)))
}

@Test
fun `getSentMessages Should get a list of prior notification sent messages`() {
val fakeReportId = "FAKE_REPORT_ID"

// Given
given(getPriorNotificationSentMessages.execute(fakeReportId)).willReturn(
listOf(
PriorNotificationSentMessage(
id = 1,
communicationMeans = "EMAIL",
dateTimeUtc = ZonedDateTime.now(),
errorMessage = null,
priorNotificationReportId = fakeReportId,
priorNotificationSource = "LOGBOOK",
recipientAddressOrNumber = "[email protected]",
success = true,
),
PriorNotificationSentMessage(
id = 2,
communicationMeans = "SMS",
dateTimeUtc = ZonedDateTime.now(),
errorMessage = null,
priorNotificationReportId = fakeReportId,
priorNotificationSource = "MANUAL",
recipientAddressOrNumber = "+33123456789",
success = true,
),
),
)

// When
api.perform(get("/bff/v1/prior_notifications/$fakeReportId/sent_messages"))
// Then
.andExpect(status().isOk)
.andExpect(jsonPath("$.length()", equalTo(2)))
.andExpect(jsonPath("$[0].communicationMeans", equalTo("EMAIL")))
.andExpect(jsonPath("$[1].communicationMeans", equalTo("SMS")))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package fr.gouv.cnsp.monitorfish.infrastructure.database.repositories

import org.assertj.core.api.Assertions.assertThat
import org.junit.jupiter.api.Test
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.transaction.annotation.Transactional

class JpaPriorNotificationSentMessageITests : AbstractDBTests() {
@Autowired
private lateinit var jpaPriorNotificationSentMessageRepository: JpaPriorNotificationSentMessageRepository

@Test
@Transactional
fun `findAllByReportId Should return the expected sent messages`() {
// Given
val reportId = "FAKE_OPERATION_103"

// When
val result = jpaPriorNotificationSentMessageRepository.findAllByReportId(reportId)

// Then
assertThat(result).isNotEmpty()
}
}
1 change: 1 addition & 0 deletions frontend/src/api/constants.ts
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ export enum HttpStatusCode {
export enum RtkCacheTagType {
PriorNotification = 'PriorNotification',
PriorNotificationDocuments = 'PriorNotificationDocuments',
PriorNotificationSentMessages = 'PriorNotificationSentMessages',
PriorNotificationTypes = 'PriorNotificationTypes',
PriorNotifications = 'PriorNotifications',
PriorNotificationsToVerify = 'PriorNotificationsToVerify',
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,14 @@ export namespace PriorNotification {
name: string
}

export type SentMessage = {
communicationMeans: 'EMAIL' | 'FAX' | 'SMS'
dateTimeUtc: string
errorMessage: string | undefined
recipientAddressOrNumber: string
success: boolean
}

export type Upload = {
createdAt: string
fileName: string
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ const CREATE_PRIOR_NOTIFICATION_ERROR_MESSAGE = "Nous n'avons pas pu créé le p
const DELETE_PRIOR_NOTIFICATION_UPLOAD_ERROR_MESSAGE = "Nous n'avons pas pu supprimer ce document attaché."
const GET_PRIOR_NOTIFICATION_UPLOADS_ERROR_MESSAGE =
"Nous n'avons pas pu récupérer les documents attachés à ce préavis."
const GET_PRIOR_NOTIFICATION_SENT_MESSAGES_ERROR_MESSAGE =
"Nous n'avons pas pu récupérer la liste des envois correspondant à ce préavis."
const UPDATE_PRIOR_NOTIFICATION_ERROR_MESSAGE = "Nous n'avons pas pu modifier le préavis."
const GET_PRIOR_NOTIFICATION_DETAIL_ERROR_MESSAGE = "Nous n'avons pas pu récupérer le préavis."
const GET_PRIOR_NOTIFICATIONS_ERROR_MESSAGE = "Nous n'avons pas pu récupérer la liste des préavis."
Expand Down Expand Up @@ -128,6 +130,13 @@ export const priorNotificationApi = monitorfishApi.injectEndpoints({
transformErrorResponse: response => new FrontendApiError(GET_PRIOR_NOTIFICATIONS_ERROR_MESSAGE, response)
}),

getPriorNotificationSentNessages: builder.query<PriorNotification.SentMessage[], string>({
providesTags: () => [{ type: RtkCacheTagType.PriorNotificationSentMessages }],
query: reportId => `/prior_notifications/${reportId}/sent_messages`,
transformErrorResponse: response =>
new FrontendApiError(GET_PRIOR_NOTIFICATION_SENT_MESSAGES_ERROR_MESSAGE, response)
}),

getPriorNotificationsToVerify: builder.query<LogbookMessage.ApiListExtraData, void>({
providesTags: () => [{ type: RtkCacheTagType.PriorNotificationsToVerify }],
query: () => '/prior_notifications/to_verify',
Expand Down
Loading