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

Consultation de la liste des PNOs #2982

Merged
merged 82 commits into from
Mar 27, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
82 commits
Select commit Hold shift + click to select a range
4c618c5
Create pno types tables
VincentAntoine Feb 14, 2024
1da018e
Add test data
VincentAntoine Feb 14, 2024
9cca201
Add init_pno_types flow
VincentAntoine Feb 14, 2024
7c3eaef
Register init_pno_types flow
VincentAntoine Feb 14, 2024
a0ad96d
Extract predicted landing datetime from PNOs
VincentAntoine Feb 16, 2024
026e390
Add ADR for prior notifications and pno types
VincentAntoine Feb 27, 2024
27ac5c7
Lint
VincentAntoine Feb 29, 2024
0cedb35
Update logbook test data
VincentAntoine Feb 29, 2024
f516872
Update pno_types test data
VincentAntoine Feb 29, 2024
2477a05
WIP
VincentAntoine Feb 29, 2024
c65daf6
Mose segments test data to fixture
VincentAntoine Mar 1, 2024
5df059b
Share segments fixtures
VincentAntoine Mar 1, 2024
d872e2e
Remove unused code
VincentAntoine Mar 1, 2024
a604956
Update logbook_reports migration
VincentAntoine Mar 1, 2024
cf90d0f
Add enriched_logbook flow
VincentAntoine Mar 2, 2024
9c0cef6
Update backend pno_types test data
VincentAntoine Mar 2, 2024
873fda5
Set empty list instead of null when enriching logbook_reports
VincentAntoine Mar 2, 2024
079b76d
Add enriched logbook_reports backend test data
VincentAntoine Mar 2, 2024
e8b59f2
Update test data
VincentAntoine Mar 2, 2024
60c52fc
Update test data
VincentAntoine Mar 2, 2024
81a5e07
Add prior notification list & filters in Frontend
ivangabriele Feb 15, 2024
5344560
Fix tests
VincentAntoine Mar 5, 2024
b7fafcd
Extract catch_to_land from PNOs
VincentAntoine Mar 11, 2024
4a274ea
Add catch_to_land in backend
VincentAntoine Mar 11, 2024
717b745
Move pno_types info into field
VincentAntoine Mar 11, 2024
80c4e57
Add test data seed generator
ivangabriele Mar 11, 2024
70eed6e
Handle empty trip_gears lists in enrich_logbook
VincentAntoine Mar 12, 2024
20d2079
Fix pno_species_and_gears query
VincentAntoine Mar 12, 2024
98ed845
Add basic prior notification list & filters Backend
ivangabriele Mar 13, 2024
adfddb6
Add update-test-data command in Makefile
ivangabriele Mar 15, 2024
9d16850
Finalize prior notification list filters
ivangabriele Mar 15, 2024
5c5ed81
Split internal migration file
ivangabriele Mar 15, 2024
ebe4370
Remove useless get-prior-notification stub
ivangabriele Mar 15, 2024
0c7f1c8
Remove useless PriorNotificationFilter in Backend
ivangabriele Mar 15, 2024
7f918a2
Add Cypress before all hook to warm up the app
ivangabriele Mar 15, 2024
29a26db
Move Backend filters into domain
ivangabriele Mar 15, 2024
a333bc3
Fix reporitories imports in prior notification use cases
ivangabriele Mar 15, 2024
087ee58
Limit Cypress before all warmup to CI
ivangabriele Mar 15, 2024
aa2aaed
Restore default null values in Backend Port entity
ivangabriele Mar 15, 2024
4605332
Update reporting unit tests in Backend
ivangabriele Mar 15, 2024
e3f16af
Split findVessel() from findVesselById() in vessel repository
ivangabriele Mar 15, 2024
28d1fc8
Fix and increase reporting repository unit tests
ivangabriele Mar 15, 2024
f0c8210
Update vessel use cases unit tests in Backend
ivangabriele Mar 15, 2024
3a50591
Add missing any param in GetAllCurrentReportings unit test
ivangabriele Mar 15, 2024
0f70500
Remove Cypress before all warmup
ivangabriele Mar 15, 2024
a9cdbf3
Add a 15 minutes delay to logbook report fake data to restore healthc…
ivangabriele Mar 15, 2024
10f7c8f
Wait for 5s instead of 10 in Cypress loadPath() command
ivangabriele Mar 15, 2024
3c29626
Add auto-generation warning comment in test data generator script
ivangabriele Mar 15, 2024
903665d
Clean a few things
ivangabriele Mar 15, 2024
93f0cbc
Add logbook report repository unit tests for findAllPriorNotifications()
ivangabriele Mar 20, 2024
e33f13e
Add prior notification list filter bar e2e tests
ivangabriele Mar 20, 2024
09b03d0
Minor corrections
VincentAntoine Mar 20, 2024
d9272b2
Minor correction
VincentAntoine Mar 20, 2024
59e0808
Fix arrival date filtering in prior notification list
ivangabriele Mar 20, 2024
ed2f570
Remove useless vessel resolution from GetPriorNotifications use case …
ivangabriele Mar 21, 2024
654679a
Add filter tags in prior notification list
ivangabriele Mar 22, 2024
f69f503
Make filter param non-nullable in LogbookReportRepository.findAllPrio…
ivangabriele Mar 22, 2024
0db44d7
Remove useless LogbookReportSpecification in Backend
ivangabriele Mar 22, 2024
b143013
Add comments in LogbookReportRepository unit tests
ivangabriele Mar 22, 2024
f4ecb53
Restore Husky pre-commit hook
ivangabriele Mar 22, 2024
38f5534
Lint Backend
ivangabriele Mar 22, 2024
ea5f06d
Fix typos and some error messages
ivangabriele Mar 22, 2024
167155b
Fix case on json property
VincentAntoine Mar 22, 2024
ec8316d
Fix prior notifications filter bar e2e tests
ivangabriele Mar 24, 2024
66e3953
Replace dash with underscore in /bff/v1/prior_notifications route
ivangabriele Mar 24, 2024
21350a6
Refactor multiple prior notifications code parts
ivangabriele Mar 24, 2024
f02b04c
Fix some dates format in PNO logbook reports test data
ivangabriele Mar 24, 2024
fd87035
Add getUrlOrPathWithQueryParams() unit tests
ivangabriele Mar 24, 2024
9bc737d
Add GetPrioNotifications use case unit test in Backend
ivangabriele Mar 24, 2024
ddc742c
Add PriorNotificationController unit test in Backend
ivangabriele Mar 24, 2024
3098ede
Add GetPrioNotificationTypes use case unit test in Backend
ivangabriele Mar 25, 2024
19e96b8
Add multiple filter unit test for jpaLogbookReportRepository.findAllP…
ivangabriele Mar 25, 2024
19b5a43
Refactor multiple code parts in prior notification
ivangabriele Mar 25, 2024
0e63360
Clean and optimize prior notification relations in Backend
ivangabriele Mar 26, 2024
0dd67be
Simplify prior notification sea front prop in Backend
ivangabriele Mar 26, 2024
c440d50
Replace LogbookMessagePNOPurposeType constant with PriorNotification …
ivangabriele Mar 26, 2024
b1e01dd
Update port repository unit test in Backend
ivangabriele Mar 26, 2024
71f66bf
Add an extra department for undefined cases in useGetPortsAsTreeOptio…
ivangabriele Mar 26, 2024
f9c4efa
Improve auto-generated test data comment
ivangabriele Mar 26, 2024
7a9f47d
Add under charter dot in VesselRiskFactor & disable interactivity in …
ivangabriele Mar 27, 2024
e876c2e
Remove useless object param values support in getUrlOrPathWithQueryPa…
ivangabriele Mar 27, 2024
80e90d4
Merge logbook message trip gear and gear type in Backend
ivangabriele Mar 27, 2024
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
3 changes: 3 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,9 @@ clean: docker-env
check-clean-archi:
cd backend/tools && ./check-clean-architecture.sh

update-test-data:
cd frontend && node ./scripts/generate_test_data_seeds.mjs

################################################################################
# Testing

Expand Down
94 changes: 94 additions & 0 deletions adrs/0004-prior-notifications-architecture-and-typing.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
# Architecture de données et typage des préavis

Date: 27/02/2024

## Statut

Résolu.

## Contexte

Le développement de la brique de gestion des préavis dans Monitorfish, en remplacement de Trident qui assurait
jusqu'ici cette gestion, nous amène à définir une **architecture de données** pour leur stockage en base de données
ainsi qu'une **stratégie de typage** permettant la catégorisation de ces préavis à des fins de lecture opérationnelle
rapide des préavis entrants.

**Concernant l'architecture** : les données provenant de deux sources différentes (logbook pour les préavis des navires
de plus de 12 m, saisie dans Monitorfish pour les navires de moins de 12 m), il apparait naturel de stocker ces
données séparément dans une table correspondant à chaque source :
- la table `logbook_reports` déjà existante contient déjà les données de préavis qu'il s'agit ici d'exploiter pour les
navires >= 12m
- une nouvelle table `manual_pnos` pour les préavis saisis dans Monitorfish

Le choix qui reste à faire concerne le mode de stockage de l'information de type : en effet, les critères de typage
(espèces, quantités...) correspondant à chaque type de préavis pouvant évoluer dans le temps, le format de stockage de
la donnée de type doit être défini en ayant en tête cette variabilité et les questions d'historisation qui en
découlent.

**Concernant le typage** : plusieurs contraintes rendent la tâche de typage non triviale :

- Les données sont entrées à des **temporalités différentes** (batch chaque minute pour les données logbook, temps réel
au moment de la saisie pour les préavis saisis dans l'app)
- Les données sont écrites en base par des **composants différents** : un `flow` pour les données issues de logbook,
le backend pour les données saisies dans l'app

Il faut donc définir quel(s) composant(s) (pipeline et / ou backend) ont la responsabilité du typage, et à quel moment
(précalcul avec stockage de l'information de type de chaque préavis, ou calcul à la volée au moment de la requête, sans
stockage).

#### Stratégie #1 : typage précalculé en batch de tous les PNOs par la pipeline

Dans cette stratégie, c'est un `flow` de la pipeline qui ajoute l'information de type à la fois dans les PNO manuels et
dans les PNO issus de logbook.

La problématique d'historisation est traitée en stockant dans chaque PNO les informations liées au type.

Avantages :
- segments des marées passées disponibles
- performance en requête sur des préavis déjà typés
- réutilisation du code de typage par la pipeline pour les deux sources de données

Inconvénients :
- gestion d'un état transitoire en front entre le moment où un préavis est saisi et le moment où la pipeline lui a
attribué un type
- complexité à gérer en cas de modification d'un préavis manuel : il faut signaler à la pipeline qu'il faut recalculer
le type du préavis. De ce fait, une incertitude existe à tout moment sur l'exactitude de l'information de type des
préavis manuels.

#### Option 2 : typage à la volée par le backend au moment de la requête

Dans cette stratégie, c'est au moment de la requête que les types de préavis sont calculés par le back.

Avantages :
- réutilisation du code de typage par le backend pour les deux sources de données
- pas de problème de latence entre saisie d'un préavis et attribution d'un type

Inconvénients :
- performances possiblement faibles sur des requêtes de larges plages de dates
- segments de flotte non disponibles sur préavis passés (uniquement segments de la marée en cours)

#### Option 3 : typage précalculé par la pipeline (données logbook) et par le backend (préavis manuels)

Dans cette stratégie :
- un `flow` de la pipeline ajoute l'information de type dans les PNO issus de logbook.
- le backend ajoute l'information de type dans les PNO manuels au moment de la saisie

Avantages :
- segments des marées passées disponibles
- performance en requête sur des préavis déjà typés
- pas de problème de latence entre saisie d'un préavis et attribution d'un type

Inconvénients :
- logique de typage à implémenter à la fois en backend et dans la pipeline

## Décision

La stratégie n°3 a été choisie afin d'avoir à la fois la performance y compris sur de larges volumes de données
passées, la disponibilité des données de segments des marées passées et éviter les problématiques de latence liées à la stratégie n°1.

![Vue schématique des tables et flux de données de préavis](images/pno_types_architecture.png "Architecture des préavis et de leur types").

## Conséquences

Il faudra tester exhaustivement les logiques de typage dans le backend et dans la pipeline pour s'assurer qu'elles
ivangabriele marked this conversation as resolved.
Show resolved Hide resolved
sont identiques.
Binary file added adrs/images/pno_types_architecture.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ data class Catch(
var weight: Double? = null,
@JsonProperty("nbFish")
var numberFish: Double? = null,
/** Species FAO code. */
var species: String? = null,
var speciesName: String? = null,
var faoZone: String? = null,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.fasterxml.jackson.annotation.JsonTypeName

@JsonTypeName("gear")
class Gear() {
/** Gear code. */
var gear: String? = null
var gearName: String? = null
var mesh: Double? = null
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,20 @@ data class LogbookMessage(
val tripNumber: String? = null,
val referencedReportId: String? = null,
var isCorrected: Boolean? = false,
val isEnriched: Boolean,
val operationType: LogbookOperationType,
val operationDateTime: ZonedDateTime,
val internalReferenceNumber: String? = null,
val externalReferenceNumber: String? = null,
val ircs: String? = null,
val vesselName: String? = null,
// ISO Alpha-3 country code
val flagState: String? = null,
val imo: String? = null,
val messageType: String? = null,
// Submission date of the report by the vessel
val reportDateTime: ZonedDateTime? = null,
// Reception date of the report by the data center
val integrationDateTime: ZonedDateTime,
var acknowledge: Acknowledge? = null,
var deleted: Boolean? = false,
Expand All @@ -30,4 +34,6 @@ data class LogbookMessage(
val transmissionFormat: LogbookTransmissionFormat,
val software: String? = null,
var isSentByFailoverSoftware: Boolean = false,
val tripGears: List<Gear>? = listOf(),
val tripSegments: List<LogbookTripSegment>? = listOf(),
)
Original file line number Diff line number Diff line change
@@ -1,8 +1,15 @@
package fr.gouv.cnsp.monitorfish.domain.entities.logbook

enum class LogbookOperationType {
/** Transmission. */
DAT,

/** Correction. */
COR,

/** Suppression. */
DEL,

/** Acquittement. */
RET,
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package fr.gouv.cnsp.monitorfish.domain.entities.logbook

import com.fasterxml.jackson.annotation.JsonProperty

data class LogbookTripSegment(
@JsonProperty("segment")
val code: String,
@JsonProperty("segmentName")
val name: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package fr.gouv.cnsp.monitorfish.domain.entities.logbook.messages

import com.fasterxml.jackson.annotation.JsonProperty
import fr.gouv.cnsp.monitorfish.domain.entities.logbook.Catch
import fr.gouv.cnsp.monitorfish.domain.entities.prior_notification.PriorNotificationType
import java.time.ZonedDateTime

class PNO() : LogbookMessageValue {
Expand All @@ -11,13 +12,20 @@ class PNO() : LogbookMessageValue {
var statisticalRectangle: String? = null
var latitude: Double? = null
var longitude: Double? = null
var pnoTypes: List<PriorNotificationType> = listOf()
var purpose: String? = null

/** Port locode. */
var port: String? = null
var portName: String? = null
var catchOnboard: List<Catch> = listOf()
var catchToLand: List<Catch> = listOf()

@JsonProperty("predictedArrivalDatetimeUtc")
var predictedArrivalDateTime: ZonedDateTime? = null

@JsonProperty("predictedLandingDatetimeUtc")
var predictedLandingDatetime: ZonedDateTime? = null

var tripStartDate: ZonedDateTime? = null
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ data class Port(
val locode: String,
val name: String,
val facade: String? = null,
val faoAreas: List<String> = listOf(),
val faoAreas: List<String> = emptyList(),
val latitude: Double? = null,
val longitude: Double? = null,
val region: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package fr.gouv.cnsp.monitorfish.domain.entities.prior_notification

import fr.gouv.cnsp.monitorfish.domain.entities.logbook.LogbookMessage
import fr.gouv.cnsp.monitorfish.domain.entities.port.Port
import fr.gouv.cnsp.monitorfish.domain.entities.risk_factor.VesselRiskFactor
import fr.gouv.cnsp.monitorfish.domain.entities.vessel.Vessel

data class PriorNotification(
val id: Long,
val logbookMessage: LogbookMessage,
val port: Port? = null,
val reportingsCount: Int? = null,
val seaFront: String? = null,
val vessel: Vessel,
val vesselRiskFactor: VesselRiskFactor?,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package fr.gouv.cnsp.monitorfish.domain.entities.prior_notification

import com.fasterxml.jackson.annotation.JsonProperty

data class PriorNotificationType(
val hasDesignatedPorts: Boolean,
val minimumNotificationPeriod: Double,
@JsonProperty("pnoTypeName")
val name: String,
)
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ data class Vessel(
val ircs: String? = null,
val externalReferenceNumber: String? = null,
val vesselName: String? = null,
// ISO Alpha-2 country code
val flagState: CountryCode,
val width: Double? = null,
val length: Double? = null,
Expand All @@ -37,11 +38,12 @@ data class Vessel(
val underCharter: Boolean? = null,
) {
fun getNationalIdentifier(): String {
val internalReferenceNumberCountryCode = LIKELY_CONTROLLED_COUNTRY_CODES.find { countryAlpha3 ->
internalReferenceNumber?.contains(
countryAlpha3,
) ?: false
}
val internalReferenceNumberCountryCode =
LIKELY_CONTROLLED_COUNTRY_CODES.find { countryAlpha3 ->
internalReferenceNumber?.contains(
countryAlpha3,
) ?: false
}
val identifier = internalReferenceNumber?.replace("${internalReferenceNumberCountryCode}000", "") ?: ""

if (districtCode.isNullOrEmpty()) {
Expand All @@ -52,47 +54,48 @@ data class Vessel(
}
}

val LIKELY_CONTROLLED_COUNTRY_CODES = listOf(
CountryCode.FR.alpha3,
CountryCode.RU.alpha3,
CountryCode.KR.alpha3,
CountryCode.JP.alpha3,
CountryCode.LY.alpha3,
CountryCode.VE.alpha3,
CountryCode.SC.alpha3,
CountryCode.AU.alpha3,
CountryCode.CN.alpha3,
CountryCode.MG.alpha3,
CountryCode.BR.alpha3,
CountryCode.PL.alpha3,
CountryCode.VU.alpha3,
CountryCode.KM.alpha3,
CountryCode.MC.alpha3,
CountryCode.BW.alpha3,
CountryCode.AI.alpha3,
CountryCode.LK.alpha3,
CountryCode.TW.alpha3,
CountryCode.TT.alpha3,
CountryCode.FO.alpha3,
CountryCode.GY.alpha3,
CountryCode.PA.alpha3,
CountryCode.SX.alpha3,
CountryCode.TN.alpha3,
CountryCode.TR.alpha3,
CountryCode.AL.alpha3,
CountryCode.GD.alpha3,
CountryCode.DZ.alpha3,
CountryCode.SX.alpha3,
CountryCode.BE.alpha3,
CountryCode.DK.alpha3,
CountryCode.DE.alpha3,
CountryCode.EE.alpha3,
CountryCode.IE.alpha3,
CountryCode.ES.alpha3,
CountryCode.IT.alpha3,
CountryCode.NL.alpha3,
CountryCode.NO.alpha3,
CountryCode.PT.alpha3,
CountryCode.SE.alpha3,
CountryCode.GB.alpha3,
)
val LIKELY_CONTROLLED_COUNTRY_CODES =
listOf(
CountryCode.FR.alpha3,
CountryCode.RU.alpha3,
CountryCode.KR.alpha3,
CountryCode.JP.alpha3,
CountryCode.LY.alpha3,
CountryCode.VE.alpha3,
CountryCode.SC.alpha3,
CountryCode.AU.alpha3,
CountryCode.CN.alpha3,
CountryCode.MG.alpha3,
CountryCode.BR.alpha3,
CountryCode.PL.alpha3,
CountryCode.VU.alpha3,
CountryCode.KM.alpha3,
CountryCode.MC.alpha3,
CountryCode.BW.alpha3,
CountryCode.AI.alpha3,
CountryCode.LK.alpha3,
CountryCode.TW.alpha3,
CountryCode.TT.alpha3,
CountryCode.FO.alpha3,
CountryCode.GY.alpha3,
CountryCode.PA.alpha3,
CountryCode.SX.alpha3,
CountryCode.TN.alpha3,
CountryCode.TR.alpha3,
CountryCode.AL.alpha3,
CountryCode.GD.alpha3,
CountryCode.DZ.alpha3,
CountryCode.SX.alpha3,
CountryCode.BE.alpha3,
CountryCode.DK.alpha3,
CountryCode.DE.alpha3,
CountryCode.EE.alpha3,
CountryCode.IE.alpha3,
CountryCode.ES.alpha3,
CountryCode.IT.alpha3,
CountryCode.NL.alpha3,
CountryCode.NO.alpha3,
CountryCode.PT.alpha3,
CountryCode.SE.alpha3,
CountryCode.GB.alpha3,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
package fr.gouv.cnsp.monitorfish.domain.filters

data class LogbookReportFilter(
val flagStates: List<String>? = null,
val isLessThanTwelveMetersVessel: Boolean? = null,
val lastControlledAfter: String? = null,
val lastControlledBefore: String? = null,
val portLocodes: List<String>? = null,
val priorNotificationTypes: List<String>? = null,
val searchQuery: String? = null,
val specyCodes: List<String>? = null,
val tripSegmentSegments: List<String>? = null,
val tripGearCodes: List<String>? = null,
val willArriveAfter: String? = null,
val willArriveBefore: String? = null,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package fr.gouv.cnsp.monitorfish.domain.filters

import fr.gouv.cnsp.monitorfish.domain.entities.reporting.ReportingType

data class ReportingFilter(
val isArchived: Boolean? = null,
val isDeleted: Boolean? = null,
val types: List<ReportingType>? = null,
val vesselInternalReferenceNumbers: List<String>? = null,
)
Loading
Loading