From 7d4516ee68990f7eafec3a604070600472e823fd Mon Sep 17 00:00:00 2001 From: lykmapipo Date: Mon, 22 Jun 2026 23:57:57 +0300 Subject: [PATCH] feat(fourwings): add utility properties to FourWingsReportResult This: - Add `vessel_ids` property to extract and strip unique, non-null AIS vessel identifiers (IDs) - Add `first_transmission_dates` property to collect unique list AIS first transmission dates - Add `last_transmission_dates` property to collect unique list AIS last transmission dates --- .../fourwings/report/models/response.py | 77 ++++++++++++++++++- .../fourwings/models/test_response_models.py | 39 ++++++++++ 2 files changed, 115 insertions(+), 1 deletion(-) diff --git a/src/gfwapiclient/resources/fourwings/report/models/response.py b/src/gfwapiclient/resources/fourwings/report/models/response.py index a925d62..cf725d7 100644 --- a/src/gfwapiclient/resources/fourwings/report/models/response.py +++ b/src/gfwapiclient/resources/fourwings/report/models/response.py @@ -2,7 +2,7 @@ import datetime -from typing import Any, List, Optional, Type +from typing import Any, Iterator, List, Optional, Type from pydantic import Field, field_validator @@ -164,3 +164,78 @@ def __init__(self, data: List[FourWingsReportItem]) -> None: The list of report items. """ super().__init__(data=data) + + @property + def vessel_ids(self) -> List[str]: + """Returns AIS vessel identifiers (IDs). + + Returns: + List[str]: + Valid list of AIS vessel identifier (ID). + """ + + def extract_vessel_ids(item: FourWingsReportItem) -> Iterator[Optional[str]]: + yield item.vessel_id + + mapped_vessel_ids: Iterator[Optional[str]] = self.flat_map( + mapper=extract_vessel_ids + ) + matched_vessel_ids: List[str] = list( + {_vessel_id.strip() for _vessel_id in mapped_vessel_ids if _vessel_id} + ) + + return matched_vessel_ids + + @property + def first_transmission_dates(self) -> List[datetime.date]: + """Returns AIS transmission start dates. + + Returns: + List[str]: + Valid list of AIS first transmission date. + """ + + def extract_first_transmission_date( + item: FourWingsReportItem, + ) -> Iterator[Optional[datetime.datetime]]: + yield item.first_transmission_date + + mapped_first_transmission_dates: Iterator[Optional[datetime.datetime]] = ( + self.flat_map(mapper=extract_first_transmission_date) + ) + ais_first_transmission_dates: List[datetime.date] = list( + { + _first_transmission_date.date() + for _first_transmission_date in mapped_first_transmission_dates + if _first_transmission_date + } + ) + + return ais_first_transmission_dates + + @property + def last_transmission_dates(self) -> List[datetime.date]: + """Returns AIS transmission end dates. + + Returns: + List[str]: + Valid list of AIS last transmission date. + """ + + def extract_last_transmission_date( + item: FourWingsReportItem, + ) -> Iterator[Optional[datetime.datetime]]: + yield item.last_transmission_date + + mapped_last_transmission_dates: Iterator[Optional[datetime.datetime]] = ( + self.flat_map(mapper=extract_last_transmission_date) + ) + ais_last_transmission_dates: List[datetime.date] = list( + { + _last_transmission_date.date() + for _last_transmission_date in mapped_last_transmission_dates + if _last_transmission_date + } + ) + + return ais_last_transmission_dates diff --git a/tests/resources/fourwings/models/test_response_models.py b/tests/resources/fourwings/models/test_response_models.py index 67c0e0b..8322bb4 100644 --- a/tests/resources/fourwings/models/test_response_models.py +++ b/tests/resources/fourwings/models/test_response_models.py @@ -46,3 +46,42 @@ def test_fourwings_report_result_deserializes_all_fields( ] result = FourWingsReportResult(data=data) assert cast(List[FourWingsReportItem], result.data()) == data + + +def test_fourwings_report_result_vessel_ids_returns_correctly( + mock_raw_fourwings_report_item: Dict[str, Any], +) -> None: + """Test that `FourWingsReportResult` returns list of vessel ids correctly.""" + data: List[FourWingsReportItem] = [ + FourWingsReportItem(**mock_raw_fourwings_report_item) + ] + result = FourWingsReportResult(data=data) + assert result.vessel_ids is not None + assert isinstance(result.vessel_ids, list) + assert len(result.vessel_ids) >= 1 + + +def test_fourwings_report_result_first_transmission_dates_returns_correctly( + mock_raw_fourwings_report_item: Dict[str, Any], +) -> None: + """Test that `FourWingsReportResult` first transmission dates returns list of first transmission dates correctly.""" + data: List[FourWingsReportItem] = [ + FourWingsReportItem(**mock_raw_fourwings_report_item) + ] + result = FourWingsReportResult(data=data) + assert result.first_transmission_dates is not None + assert isinstance(result.first_transmission_dates, list) + assert len(result.first_transmission_dates) >= 1 + + +def test_fourwings_report_result_last_transmission_dates_returns_correctly( + mock_raw_fourwings_report_item: Dict[str, Any], +) -> None: + """Test that `FourWingsReportResult` last transmission dates to returns list of last transmission dates correctly.""" + data: List[FourWingsReportItem] = [ + FourWingsReportItem(**mock_raw_fourwings_report_item) + ] + result = FourWingsReportResult(data=data) + assert result.last_transmission_dates is not None + assert isinstance(result.last_transmission_dates, list) + assert len(result.last_transmission_dates) >= 1