Skip to content

Commit abdc96f

Browse files
committed
✅(ingestion-infrastructure) add metiers repository tests for specifics
1 parent 37a9cfc commit abdc96f

3 files changed

Lines changed: 133 additions & 16 deletions

File tree

src/web/infrastructure/repositories/shared/postgres_metier_repository.py

Lines changed: 20 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,14 @@ def get_by_external_id(self, external_id: str) -> Metier:
9696
f"Metier with external_id {external_id} not found"
9797
) from e
9898

99+
def get_all(self) -> List[Metier]:
100+
metier_models = MetierModel.objects.all()
101+
return [model.to_entity() for model in metier_models]
102+
103+
def filter_by(self, predicate: Dict[str, str], limit: int = 1000) -> List[Metier]:
104+
metier_models = MetierModel.objects.filter(**predicate)[:limit]
105+
return [model.to_entity() for model in metier_models]
106+
99107
@transaction.atomic
100108
def get_pending_processing(self, limit: int = 1000) -> List[Metier]:
101109
qs = (
@@ -113,22 +121,18 @@ def get_pending_processing(self, limit: int = 1000) -> List[Metier]:
113121

114122
return [model.to_entity() for model in qs]
115123

116-
def get_all(self) -> List[Metier]:
117-
metier_models = MetierModel.objects.all()
118-
return [model.to_entity() for model in metier_models]
119-
120-
def filter_by(self, predicate: Dict[str, str], limit: int = 1000) -> List[Metier]:
121-
metier_models = MetierModel.objects.filter(**predicate)[:limit]
122-
return [model.to_entity() for model in metier_models]
123-
124124
def mark_as_processed(self, metiers_list: List[Metier]) -> int:
125-
metier_ids = [metier.id for metier in metiers_list]
126-
return MetierModel.objects.filter(id__in=metier_ids).update(
127-
processing=False, processed_at=timezone.now()
128-
)
125+
try:
126+
return MetierModel.objects.filter(
127+
id__in=[obj.id for obj in metiers_list]
128+
).update(processed_at=timezone.now(), processing=False)
129+
except Exception as e:
130+
raise DatabaseError(f"Database error during update: {str(e)}") from e
129131

130132
def mark_as_pending(self, metiers_list: List[Metier]) -> int:
131-
metier_ids = [metier.id for metier in metiers_list]
132-
return MetierModel.objects.filter(id__in=metier_ids).update(
133-
processing=True, processed_at=None
134-
)
133+
try:
134+
return MetierModel.objects.filter(
135+
id__in=[obj.id for obj in metiers_list]
136+
).update(processing=False)
137+
except Exception as e:
138+
raise DatabaseError(f"Database error during update: {str(e)}") from e

src/web/tests/factories/metier_factory.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
1+
from datetime import datetime
12
from typing import List, Optional
23
from uuid import UUID, uuid4
34

5+
from django.utils import timezone
46
from faker import Faker
57
from polyfactory.factories import DataclassFactory
68

@@ -91,6 +93,10 @@ def create_model(
9193
activites: Optional[List[str]] = None,
9294
conditions_particulieres: Optional[List[str]] = None,
9395
offer_family_code: Optional[str] = None,
96+
processing: bool = False,
97+
processed_at: Optional[datetime] = None,
98+
archived_at: Optional[datetime] = None,
99+
updated_at: Optional[datetime] = None,
94100
) -> MetierModel:
95101

96102
metier = MetierFactory.create_entity(
@@ -106,8 +112,19 @@ def create_model(
106112
)
107113

108114
metier_model = MetierModel.from_entity(metier)
115+
metier_model.processing = processing
116+
metier_model.processed_at = processed_at
117+
metier_model.archived_at = archived_at
118+
metier_model.updated_at = updated_at
119+
109120
metier_model.save()
110121

122+
if updated_at is not None:
123+
MetierModel.objects.filter(pk=metier_model.pk).update(
124+
updated_at=timezone.make_aware(updated_at)
125+
)
126+
metier_model.refresh_from_db()
127+
111128
return metier_model
112129

113130
@staticmethod
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
from datetime import datetime
2+
3+
import pytest
4+
from dateutil.relativedelta import relativedelta
5+
from faker import Faker
6+
7+
from domain.entities.metier import Metier
8+
from infrastructure.django_apps.shared.models.metier import MetierModel
9+
from infrastructure.gateways.shared.logger import LoggerService
10+
from infrastructure.repositories.shared.postgres_metier_repository import (
11+
PostgresMetierRepository,
12+
)
13+
from tests.factories.metier_factory import MetierFactory
14+
15+
fake = Faker()
16+
NOW = datetime.now()
17+
DAY_AGO = NOW - relativedelta(days=1)
18+
19+
20+
@pytest.fixture(name="repository")
21+
def repository_fixture():
22+
return PostgresMetierRepository(LoggerService())
23+
24+
25+
class TestGetPendingProcessing:
26+
def test_excluded_items(self, db, repository):
27+
MetierFactory.create_model(archived_at=NOW)
28+
MetierFactory.create_model(processing=True)
29+
MetierFactory.create_model(processed_at=NOW, updated_at=DAY_AGO)
30+
31+
assert repository.get_pending_processing() == []
32+
33+
def test_get_pending_items_with_logical_lock(self, db, repository):
34+
never_processed = MetierFactory.create_model()
35+
updated_after_processed = MetierFactory.create_model(
36+
processed_at=DAY_AGO, updated_at=NOW
37+
)
38+
39+
entities = repository.get_pending_processing()
40+
assert {e.id for e in entities} == {
41+
never_processed.id,
42+
updated_after_processed.id,
43+
}
44+
45+
for entity in entities:
46+
assert isinstance(entity, Metier)
47+
48+
def test_limit(self, db, repository):
49+
MetierFactory.create_model_batch(2)
50+
51+
entities = repository.get_pending_processing(limit=1)
52+
assert len(entities) == 1
53+
assert MetierModel.objects.filter(processing=True).count() == 1
54+
assert MetierModel.objects.filter(processing=False).count() == 1
55+
56+
57+
def test_mark_as_processed(db, repository):
58+
concours_list = [
59+
MetierFactory.create_model(processing=True).to_entity(),
60+
MetierFactory.create_model(processing=False).to_entity(),
61+
]
62+
undesired_concours = MetierFactory.create_model(processing=True).to_entity()
63+
64+
count = repository.mark_as_processed(concours_list)
65+
assert count == len(concours_list)
66+
67+
model_objects = MetierModel.objects.filter(
68+
processing=False, processed_at__isnull=False
69+
)
70+
assert set(model_objects.values_list("id", flat=True)) == {
71+
concours.id for concours in concours_list
72+
}
73+
74+
undesired_model_objects = MetierModel.objects.get(
75+
processing=True, processed_at__isnull=True
76+
)
77+
assert undesired_model_objects.id == undesired_concours.id
78+
79+
80+
def test_mark_as_pending(db, repository):
81+
metiers_list = [
82+
MetierFactory.create_model(processing=True).to_entity(),
83+
MetierFactory.create_model(processing=False).to_entity(),
84+
]
85+
undesired_metiers = MetierFactory.create_model(processing=True).to_entity()
86+
87+
count = repository.mark_as_pending(metiers_list)
88+
assert count == len(metiers_list)
89+
90+
model_objects = MetierModel.objects.filter(processing=False)
91+
assert set(model_objects.values_list("id", flat=True)) == {
92+
metier.id for metier in metiers_list
93+
}
94+
95+
undesired_model_objects = MetierModel.objects.get(processing=True)
96+
assert undesired_model_objects.id == undesired_metiers.id

0 commit comments

Comments
 (0)