Skip to content

Commit b03915a

Browse files
authored
Merge pull request #516 from OP-TED/feature/TED4-85
added test package and refactored logic for eligibility checker
2 parents fa1a4eb + e45fb57 commit b03915a

422 files changed

Lines changed: 155747 additions & 24 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

ted_sws/core/model/metadata.py

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
# Email: costezki.eugen@gmail.com
77

88
""" """
9+
from enum import Enum
910
from typing import List, Optional
1011

1112
from pydantic import Field
@@ -55,6 +56,17 @@ class EncodedValue(NamedTuple):
5556
value: str = None
5657

5758

59+
class NoticeSource(str, Enum):
60+
"""
61+
Holds source of notice
62+
"""
63+
STANDARD_FORM = "standard_forms"
64+
ELECTRONIC_FORM = "eforms"
65+
66+
def __str__(self):
67+
return self.value
68+
69+
5870
class NormalisedMetadata(Metadata):
5971
"""
6072
Stores notice normalised metadata
@@ -79,9 +91,10 @@ class NormalisedMetadata(Metadata):
7991
legal_basis_directive: str
8092
form_number: str
8193
eforms_subtype: str
82-
xsd_version: str
94+
xsd_version: Optional[str]
8395
published_in_cellar_counter: int = Field(default=0)
84-
is_eform: Optional[bool] = False
96+
notice_source: Optional[NoticeSource] = NoticeSource.STANDARD_FORM
97+
eform_sdk_version: Optional[str]
8598

8699

87100
class NormalisedMetadataView(Metadata):
@@ -105,8 +118,10 @@ class NormalisedMetadataView(Metadata):
105118
legal_basis_directive: str
106119
form_number: str
107120
eforms_subtype: str
108-
xsd_version: str
121+
xsd_version: Optional[str]
109122
published_in_cellar_counter: int = Field(default=0)
123+
notice_source: Optional[NoticeSource] = NoticeSource.STANDARD_FORM
124+
eform_sdk_version: Optional[str]
110125

111126

112127

ted_sws/mapping_suite_processor/services/conceptual_mapping_generate_metadata.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
END_DATE_KEY = "end_date"
1919
MIN_XSD_VERSION_KEY = "min_xsd_version"
2020
MAX_XSD_VERSION_KEY = "max_xsd_version"
21+
EFORMS_SDK_VERSIONS_KEY = "eforms_sdk_versions"
2122
TITLE_KEY = "title"
2223
CREATED_KEY = "created_at"
2324
IDENTIFIER_KEY = "identifier"

ted_sws/notice_metadata_processor/adapters/notice_metadata_normaliser.py

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
import re
55
import pandas as pd
66

7-
from ted_sws.core.model.metadata import NormalisedMetadata, LanguageTaggedString
7+
from ted_sws.core.model.metadata import NormalisedMetadata, LanguageTaggedString, NoticeSource
88
from ted_sws.notice_metadata_processor.model.metadata import ExtractedMetadata
99
from ted_sws.notice_metadata_processor.services.metadata_constraints import filter_df_by_variables
1010
from ted_sws.resources.mapping_files_registry import MappingFilesRegistry
@@ -36,7 +36,8 @@
3636
DEADLINE_DATE_KEY = "deadline_for_submission"
3737
NOTICE_TYPE_KEY = "notice_type"
3838
XSD_VERSION_KEY = "xsd_version"
39-
IS_EFORM_KEY = "is_eform"
39+
EFORM_SDK_VERSION_KEY = "eform_sdk_version"
40+
NOTICE_SOURCE_KEY = "notice_source"
4041
ENGLISH_LANGUAGE_TAG = "EN"
4142
mapping_registry = MappingFilesRegistry()
4243

@@ -257,7 +258,7 @@ def normalise_metadata(self, extracted_metadata: ExtractedMetadata) -> Normalise
257258
LEGAL_BASIS_DIRECTIVE_KEY: get_map_value(mapping=legal_basis_map, value=legal_basis),
258259
E_FORMS_SUBTYPE_KEY: str(eforms_subtype),
259260
XSD_VERSION_KEY: extracted_metadata.xml_schema_version,
260-
IS_EFORM_KEY: False
261+
NOTICE_SOURCE_KEY: NoticeSource.STANDARD_FORM
261262
}
262263

263264
return NormalisedMetadata(**metadata)
@@ -339,8 +340,8 @@ def normalise_metadata(self, extracted_metadata: ExtractedMetadata) -> Normalise
339340
LEGAL_BASIS_DIRECTIVE_KEY: get_map_value(mapping=legal_basis_map,
340341
value=legal_basis),
341342
E_FORMS_SUBTYPE_KEY: extracted_metadata.extracted_notice_subtype,
342-
XSD_VERSION_KEY: extracted_metadata.xml_schema_version,
343-
IS_EFORM_KEY: True
343+
EFORM_SDK_VERSION_KEY: extracted_metadata.xml_schema_version,
344+
NOTICE_SOURCE_KEY: NoticeSource.ELECTRONIC_FORM
344345
}
345346

346347
return NormalisedMetadata(**metadata)

ted_sws/notice_metadata_processor/services/notice_eligibility.py

Lines changed: 45 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,36 @@
33

44
import semantic_version
55

6-
from ted_sws.core.model.metadata import NormalisedMetadata
6+
from ted_sws.core.model.metadata import NormalisedMetadata, NoticeSource
77
from ted_sws.core.model.notice import Notice
88
from ted_sws.core.model.transform import MappingSuite
99
from ted_sws.data_manager.adapters.repository_abc import MappingSuiteRepositoryABC, NoticeRepositoryABC
1010
from ted_sws.mapping_suite_processor.services.conceptual_mapping_generate_metadata import START_DATE_KEY, END_DATE_KEY, \
11-
MIN_XSD_VERSION_KEY, MAX_XSD_VERSION_KEY, E_FORMS_SUBTYPE_KEY
11+
MIN_XSD_VERSION_KEY, MAX_XSD_VERSION_KEY, E_FORMS_SUBTYPE_KEY, EFORMS_SDK_VERSIONS_KEY
12+
13+
14+
def format_version_with_zero_patch(version_string:str) -> semantic_version.Version:
15+
"""
16+
This will take a string version (1.7 or 1.7.6) and will transform it to a semantic version with 0 as patch
17+
1.7 -> 1.7.0
18+
1.7.6 -> 1.7.0
19+
"""
20+
parsed_version = semantic_version.Version.coerce(version_string)
21+
return semantic_version.Version(major=parsed_version.major, minor=parsed_version.minor, patch=0)
22+
23+
24+
def is_date_in_range(publication_date, constraint_start_date_value, constraint_end_date_value) -> bool:
25+
"""
26+
This will return True or False if publication_date is in range looking at the start and end date constraints in the
27+
metadata of a mapping suite
28+
"""
29+
if not constraint_start_date_value and not constraint_end_date_value:
30+
return True
31+
32+
start_date = datetime.datetime.fromisoformat(constraint_start_date_value[0])
33+
end_date = datetime.datetime.fromisoformat(
34+
constraint_end_date_value[0] if constraint_end_date_value else datetime.datetime.now().isoformat())
35+
return start_date <= publication_date <= end_date
1236

1337

1438
def check_package(mapping_suite: MappingSuite, notice_metadata: NormalisedMetadata):
@@ -18,25 +42,34 @@ def check_package(mapping_suite: MappingSuite, notice_metadata: NormalisedMetada
1842
:param mapping_suite:
1943
:return:
2044
"""
45+
2146
constraints = mapping_suite.metadata_constraints.constraints
2247

2348
eform_subtype = notice_metadata.eforms_subtype
2449
notice_publication_date = datetime.datetime.fromisoformat(notice_metadata.publication_date)
25-
notice_xsd_version = notice_metadata.xsd_version
2650

27-
end_date = constraints[END_DATE_KEY][0] if constraints[END_DATE_KEY] else datetime.datetime.now().isoformat()
28-
constraint_start_date = datetime.datetime.fromisoformat(constraints[START_DATE_KEY][0])
29-
constraint_end_date = datetime.datetime.fromisoformat(end_date)
30-
constraint_min_xsd_version = constraints[MIN_XSD_VERSION_KEY][0]
31-
constraint_max_xsd_version = constraints[MAX_XSD_VERSION_KEY][0]
51+
if notice_metadata.notice_source == NoticeSource.ELECTRONIC_FORM:
52+
notice_xsd_version = notice_metadata.eform_sdk_version
53+
# eform sdk version value in metadata example: eforms-sdk-1.7 or eforms-sdk-1.7.9
54+
# we need to extract only the version i.e 1.7 or 1.7.9
55+
eforms_sdk_version = notice_xsd_version.rsplit('-', 1)[1]
56+
constraint_version_range = [format_version_with_zero_patch(version) for version in
57+
constraints[EFORMS_SDK_VERSIONS_KEY]]
58+
in_version_range = format_version_with_zero_patch(eforms_sdk_version) in constraint_version_range
59+
else:
60+
notice_xsd_version = notice_metadata.xsd_version
61+
constraint_min_xsd_version = constraints[MIN_XSD_VERSION_KEY][0]
62+
constraint_max_xsd_version = constraints[MAX_XSD_VERSION_KEY][0]
63+
in_version_range = constraint_min_xsd_version <= notice_xsd_version <= constraint_max_xsd_version
64+
65+
in_date_range = is_date_in_range(publication_date=notice_publication_date,
66+
constraint_start_date_value=constraints[START_DATE_KEY],
67+
constraint_end_date_value=constraints[END_DATE_KEY])
3268
eform_subtype_constraint_values = [str(eforms_subtype_value) for eforms_subtype_value in
3369
constraints[E_FORMS_SUBTYPE_KEY]]
34-
35-
in_date_range = constraint_start_date <= notice_publication_date <= constraint_end_date
36-
in_version_range = constraint_min_xsd_version <= notice_xsd_version <= constraint_max_xsd_version
3770
covered_eform_type = eform_subtype in eform_subtype_constraint_values
3871

39-
return True if in_date_range and in_version_range and covered_eform_type else False
72+
return in_date_range and in_version_range and covered_eform_type
4073

4174

4275
def notice_eligibility_checker(notice: Notice, mapping_suite_repository: MappingSuiteRepositoryABC) -> Tuple:

tests/conftest.py

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
NOTICE_NUMBER_KEY, PUBLICATION_DATE_KEY, OJS_NUMBER_KEY, OJS_TYPE_KEY, BUYER_CITY_KEY, BUYER_NAME_KEY, LANGUAGE_KEY, \
1919
BUYER_COUNTRY_KEY, EU_INSTITUTION_KEY, SENT_DATE_KEY, DEADLINE_DATE_KEY, NOTICE_TYPE_KEY, FORM_TYPE_KEY, \
2020
PLACE_OF_PERFORMANCE_KEY, EXTRACTED_LEGAL_BASIS_KEY, FORM_NUMBER_KEY, LEGAL_BASIS_DIRECTIVE_KEY, \
21-
E_FORMS_SUBTYPE_KEY, XSD_VERSION_KEY
21+
E_FORMS_SUBTYPE_KEY, XSD_VERSION_KEY, EFORM_SDK_VERSION_KEY, NOTICE_SOURCE_KEY
2222

2323
from tests import TEST_DATA_PATH
2424
from tests.fakes.fake_repository import FakeNoticeRepository
@@ -212,6 +212,35 @@ def normalised_metadata_object():
212212

213213
return NormalisedMetadata(**data)
214214

215+
@pytest.fixture
216+
def eform_normalised_metadata_object():
217+
data = {
218+
TITLE_KEY: [LanguageTaggedString(text="Eteläisen Salon liikuntapaikkojen hoidon hankinta", language="FIN")],
219+
LONG_TITLE_KEY: [
220+
LanguageTaggedString(text="FIN :: Eteläisen Salon liikuntapaikkojen hoidon hankinta", language="FIN")],
221+
NOTICE_NUMBER_KEY: "00622690-2023",
222+
PUBLICATION_DATE_KEY: "2023-10-13T00:00:00",
223+
OJS_NUMBER_KEY: "198/2023",
224+
OJS_TYPE_KEY: "S",
225+
BUYER_CITY_KEY: None,
226+
BUYER_NAME_KEY: None,
227+
LANGUAGE_KEY: None,
228+
BUYER_COUNTRY_KEY: None,
229+
EU_INSTITUTION_KEY: None,
230+
SENT_DATE_KEY: "2023-10-12T00:00:00",
231+
DEADLINE_DATE_KEY: None,
232+
NOTICE_TYPE_KEY: "http://publications.europa.eu/resource/authority/notice-type/cn-standard",
233+
FORM_TYPE_KEY: "http://publications.europa.eu/resource/authority/form-type/competition",
234+
PLACE_OF_PERFORMANCE_KEY: ["http://data.europa.eu/nuts/code/FI1C1"],
235+
EXTRACTED_LEGAL_BASIS_KEY: "http://publications.europa.eu/resource/authority/legal-basis/32014L0024",
236+
LEGAL_BASIS_DIRECTIVE_KEY: "http://publications.europa.eu/resource/authority/legal-basis/32014L0024",
237+
FORM_NUMBER_KEY: "",
238+
E_FORMS_SUBTYPE_KEY: "16",
239+
EFORM_SDK_VERSION_KEY: "eforms-sdk-1.7",
240+
NOTICE_SOURCE_KEY: "eforms"
241+
}
242+
243+
return NormalisedMetadata(**data)
215244

216245
@pytest.fixture
217246
@mongomock.patch(servers=(('server.example.com', 27017),))
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
{
2+
"identifier": "package_EF16",
3+
"title": "Package EF16 v1.2",
4+
"description": "This is the conceptual mapping for bla bla bla",
5+
"mapping_version": "3.0.0-alpha.1",
6+
"ontology_version": "4.0.0",
7+
"metadata_constraints": {
8+
"constraints": {
9+
"min_xsd_version": ["R2.0.9.S04.E01"],
10+
"max_xsd_version": ["R2.0.9.S04.E01"],
11+
"eforms_subtype": [
12+
"16",
13+
"10",
14+
"11",
15+
"12",
16+
"13",
17+
"X1",
18+
"T1"
19+
],
20+
"start_date": null,
21+
"end_date": null,
22+
"eforms_sdk_versions": [
23+
"1.3",
24+
"1.4",
25+
"1.5",
26+
"1.6",
27+
"1.7",
28+
"1.8",
29+
"1.9",
30+
"1.10"
31+
]
32+
}
33+
}
34+
}

0 commit comments

Comments
 (0)