e-data 2.0.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- e_data-2.0.0b1.dist-info/METADATA +214 -0
- e_data-2.0.0b1.dist-info/RECORD +21 -0
- e_data-2.0.0b1.dist-info/WHEEL +5 -0
- e_data-2.0.0b1.dist-info/licenses/LICENSE +674 -0
- e_data-2.0.0b1.dist-info/top_level.txt +1 -0
- edata/__init__.py +0 -0
- edata/const.py +56 -0
- edata/helpers.py +312 -0
- edata/tests/__init__.py +0 -0
- edata/tests/connectors/__init__.py +0 -0
- edata/tests/connectors/test_datadis_connector.py +178 -0
- edata/tests/connectors/test_redata_connector.py +29 -0
- edata/tests/services/__init__.py +0 -0
- edata/tests/services/test_billing_service.py +1169 -0
- edata/tests/services/test_consumption_service.py +955 -0
- edata/tests/services/test_contract_service.py +216 -0
- edata/tests/services/test_database_service.py +415 -0
- edata/tests/services/test_maximeter_service.py +83 -0
- edata/tests/services/test_supply_service.py +251 -0
- edata/tests/test_helpers.py +612 -0
- edata/utils.py +164 -0
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"""Tests for MaximeterService."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from unittest.mock import AsyncMock, Mock, patch
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
import pytest_asyncio
|
|
8
|
+
|
|
9
|
+
from edata.models.database import MaxPowerModel
|
|
10
|
+
from edata.services.maximeter import MaximeterService
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest_asyncio.fixture
|
|
14
|
+
async def maximeter_service():
|
|
15
|
+
"""Create a maximeter service with mocked dependencies."""
|
|
16
|
+
with patch("edata.services.maximeter.get_database_service") as mock_db_factory:
|
|
17
|
+
mock_db = Mock()
|
|
18
|
+
# Hacer que los métodos de la base de datos retornen AsyncMock
|
|
19
|
+
mock_db.get_maxpower = AsyncMock(return_value=[])
|
|
20
|
+
mock_db.save_maxpower = AsyncMock(return_value=Mock())
|
|
21
|
+
mock_db_factory.return_value = mock_db
|
|
22
|
+
|
|
23
|
+
# Create a mock DatadisConnector
|
|
24
|
+
mock_datadis_connector = Mock()
|
|
25
|
+
service = MaximeterService(datadis_connector=mock_datadis_connector)
|
|
26
|
+
service._db_service = mock_db
|
|
27
|
+
return service
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@pytest.fixture
|
|
31
|
+
def sample_maximeter():
|
|
32
|
+
"""Sample maximeter data for testing."""
|
|
33
|
+
return [
|
|
34
|
+
MaxPowerModel(
|
|
35
|
+
cups="ES001234567890123456AB",
|
|
36
|
+
datetime=datetime(2023, 1, 15, 14, 30),
|
|
37
|
+
value_kw=2.5,
|
|
38
|
+
),
|
|
39
|
+
MaxPowerModel(
|
|
40
|
+
cups="ES001234567890123456AB",
|
|
41
|
+
datetime=datetime(2023, 2, 20, 16, 45),
|
|
42
|
+
value_kw=3.2,
|
|
43
|
+
),
|
|
44
|
+
MaxPowerModel(
|
|
45
|
+
cups="ES001234567890123456AB",
|
|
46
|
+
datetime=datetime(2023, 3, 10, 12, 15),
|
|
47
|
+
value_kw=1.8,
|
|
48
|
+
),
|
|
49
|
+
]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
class TestMaximeterService:
|
|
53
|
+
"""Test class for MaximeterService."""
|
|
54
|
+
|
|
55
|
+
@pytest.mark.asyncio
|
|
56
|
+
async def test_get_maximeter_summary(self, maximeter_service, sample_maximeter):
|
|
57
|
+
"""Test getting maximeter summary."""
|
|
58
|
+
# Setup mocks
|
|
59
|
+
maximeter_service.get_stored_maxpower = AsyncMock(return_value=sample_maximeter)
|
|
60
|
+
|
|
61
|
+
# Execute
|
|
62
|
+
result = await maximeter_service.get_maximeter_summary("ES001234567890123456AB")
|
|
63
|
+
|
|
64
|
+
# Verify
|
|
65
|
+
assert result["max_power_kW"] == 3.2 # max value
|
|
66
|
+
assert result["max_power_date"] == datetime(2023, 2, 20, 16, 45)
|
|
67
|
+
assert result["max_power_mean_kW"] == 2.5 # (2.5 + 3.2 + 1.8) / 3
|
|
68
|
+
assert result["max_power_90perc_kW"] == 3.2 # 90th percentile
|
|
69
|
+
|
|
70
|
+
@pytest.mark.asyncio
|
|
71
|
+
async def test_get_maximeter_summary_no_data(self, maximeter_service):
|
|
72
|
+
"""Test getting maximeter summary with no data."""
|
|
73
|
+
# Setup mocks
|
|
74
|
+
maximeter_service.get_stored_maxpower = AsyncMock(return_value=[])
|
|
75
|
+
|
|
76
|
+
# Execute
|
|
77
|
+
result = await maximeter_service.get_maximeter_summary("ES001234567890123456AB")
|
|
78
|
+
|
|
79
|
+
# Verify
|
|
80
|
+
assert result["max_power_kW"] is None
|
|
81
|
+
assert result["max_power_date"] is None
|
|
82
|
+
assert result["max_power_mean_kW"] is None
|
|
83
|
+
assert result["max_power_90perc_kW"] is None
|
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
"""Tests for SupplyService."""
|
|
2
|
+
|
|
3
|
+
from datetime import datetime
|
|
4
|
+
from unittest.mock import AsyncMock, Mock, patch
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
import pytest_asyncio
|
|
8
|
+
|
|
9
|
+
from edata.models.database import SupplyModel
|
|
10
|
+
from edata.services.supply import SupplyService
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
@pytest_asyncio.fixture
|
|
14
|
+
async def supply_service():
|
|
15
|
+
"""Create a supply service with mocked dependencies."""
|
|
16
|
+
with patch("edata.services.supply.get_database_service") as mock_db_factory:
|
|
17
|
+
mock_db = Mock()
|
|
18
|
+
# Hacer que los métodos de la base de datos retornen AsyncMock
|
|
19
|
+
mock_db.get_supplies = AsyncMock(return_value=[])
|
|
20
|
+
mock_db.save_supply = AsyncMock(return_value=Mock())
|
|
21
|
+
mock_db_factory.return_value = mock_db
|
|
22
|
+
|
|
23
|
+
# Create a mock DatadisConnector
|
|
24
|
+
mock_datadis_connector = Mock()
|
|
25
|
+
service = SupplyService(datadis_connector=mock_datadis_connector)
|
|
26
|
+
service._db_service = mock_db
|
|
27
|
+
return service
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
@pytest.fixture
|
|
31
|
+
def sample_supplies():
|
|
32
|
+
"""Sample supply data for testing."""
|
|
33
|
+
return [
|
|
34
|
+
SupplyModel(
|
|
35
|
+
cups="ES001234567890123456AB",
|
|
36
|
+
distributor_code="123",
|
|
37
|
+
point_type=5,
|
|
38
|
+
date_start=datetime(2023, 1, 1),
|
|
39
|
+
date_end=datetime(2024, 12, 31),
|
|
40
|
+
address="Test Address 1",
|
|
41
|
+
postal_code="12345",
|
|
42
|
+
province="Test Province 1",
|
|
43
|
+
municipality="Test Municipality 1",
|
|
44
|
+
distributor="Test Distributor 1",
|
|
45
|
+
),
|
|
46
|
+
SupplyModel(
|
|
47
|
+
cups="ES987654321098765432BA",
|
|
48
|
+
distributor_code="456",
|
|
49
|
+
point_type=4,
|
|
50
|
+
date_start=datetime(2023, 6, 1),
|
|
51
|
+
date_end=datetime(2025, 6, 1),
|
|
52
|
+
address="Test Address 2",
|
|
53
|
+
postal_code="67890",
|
|
54
|
+
province="Test Province 2",
|
|
55
|
+
municipality="Test Municipality 2",
|
|
56
|
+
distributor="Test Distributor 2",
|
|
57
|
+
),
|
|
58
|
+
]
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class TestSupplyService:
|
|
62
|
+
"""Test class for SupplyService."""
|
|
63
|
+
|
|
64
|
+
@pytest.mark.asyncio
|
|
65
|
+
async def test_update_supplies_success(self, supply_service):
|
|
66
|
+
"""Test successful supply update."""
|
|
67
|
+
# Setup mocks - now returns Pydantic models
|
|
68
|
+
supply_service._datadis.get_supplies = AsyncMock(
|
|
69
|
+
return_value=[
|
|
70
|
+
SupplyModel(
|
|
71
|
+
cups="ES001234567890123456AB",
|
|
72
|
+
distributor_code="123",
|
|
73
|
+
point_type=5,
|
|
74
|
+
date_start=datetime(2023, 1, 1),
|
|
75
|
+
date_end=datetime(2024, 12, 31),
|
|
76
|
+
address="Test Address",
|
|
77
|
+
postal_code="12345",
|
|
78
|
+
province="Test Province",
|
|
79
|
+
municipality="Test Municipality",
|
|
80
|
+
distributor="Test Distributor",
|
|
81
|
+
)
|
|
82
|
+
]
|
|
83
|
+
)
|
|
84
|
+
supply_service._db_service.get_supplies.side_effect = [
|
|
85
|
+
[],
|
|
86
|
+
[Mock()],
|
|
87
|
+
] # No existing, then 1 stored
|
|
88
|
+
supply_service._db_service.save_supply.return_value = Mock()
|
|
89
|
+
|
|
90
|
+
# Execute
|
|
91
|
+
result = await supply_service.update_supplies()
|
|
92
|
+
|
|
93
|
+
# Verify
|
|
94
|
+
assert result["success"] is True
|
|
95
|
+
assert result["stats"]["fetched"] == 1
|
|
96
|
+
assert result["stats"]["saved"] == 1
|
|
97
|
+
assert result["stats"]["updated"] == 0
|
|
98
|
+
supply_service._datadis.get_supplies.assert_called_once()
|
|
99
|
+
supply_service._db_service.save_supply.assert_called_once()
|
|
100
|
+
|
|
101
|
+
@pytest.mark.asyncio
|
|
102
|
+
async def test_get_supplies(self, supply_service, sample_supplies):
|
|
103
|
+
"""Test getting supplies."""
|
|
104
|
+
# Setup mocks
|
|
105
|
+
supply_service._db_service.get_supplies.return_value = sample_supplies
|
|
106
|
+
|
|
107
|
+
# Execute
|
|
108
|
+
result = await supply_service.get_supplies()
|
|
109
|
+
|
|
110
|
+
# Verify
|
|
111
|
+
assert len(result) == 2
|
|
112
|
+
assert result[0].cups == "ES001234567890123456AB"
|
|
113
|
+
assert result[1].cups == "ES987654321098765432BA"
|
|
114
|
+
supply_service._db_service.get_supplies.assert_called_once_with(cups=None)
|
|
115
|
+
|
|
116
|
+
@pytest.mark.asyncio
|
|
117
|
+
async def test_get_supply_by_cups(self, supply_service, sample_supplies):
|
|
118
|
+
"""Test getting supply by CUPS."""
|
|
119
|
+
# Setup mocks
|
|
120
|
+
supply_service._db_service.get_supplies.return_value = [sample_supplies[0]]
|
|
121
|
+
|
|
122
|
+
# Execute
|
|
123
|
+
result = await supply_service.get_supply_by_cups("ES001234567890123456AB")
|
|
124
|
+
|
|
125
|
+
# Verify
|
|
126
|
+
assert result is not None
|
|
127
|
+
assert result.cups == "ES001234567890123456AB"
|
|
128
|
+
assert result.distributor == "Test Distributor 1"
|
|
129
|
+
supply_service._db_service.get_supplies.assert_called_once_with(
|
|
130
|
+
cups="ES001234567890123456AB"
|
|
131
|
+
)
|
|
132
|
+
|
|
133
|
+
@pytest.mark.asyncio
|
|
134
|
+
async def test_get_cups_list(self, supply_service, sample_supplies):
|
|
135
|
+
"""Test getting CUPS list."""
|
|
136
|
+
# Setup mocks
|
|
137
|
+
supply_service._db_service.get_supplies.return_value = sample_supplies
|
|
138
|
+
|
|
139
|
+
# Execute
|
|
140
|
+
result = await supply_service.get_cups_list()
|
|
141
|
+
|
|
142
|
+
# Verify
|
|
143
|
+
assert len(result) == 2
|
|
144
|
+
assert "ES001234567890123456AB" in result
|
|
145
|
+
assert "ES987654321098765432BA" in result
|
|
146
|
+
|
|
147
|
+
@pytest.mark.asyncio
|
|
148
|
+
async def test_get_active_supplies(self, supply_service, sample_supplies):
|
|
149
|
+
"""Test getting active supplies."""
|
|
150
|
+
# Setup mocks
|
|
151
|
+
supply_service._db_service.get_supplies.return_value = sample_supplies
|
|
152
|
+
|
|
153
|
+
# Execute - test with date in 2024 (both should be active)
|
|
154
|
+
result = await supply_service.get_active_supplies(datetime(2024, 6, 15))
|
|
155
|
+
|
|
156
|
+
# Verify
|
|
157
|
+
assert len(result) == 2 # Both supplies should be active in 2024
|
|
158
|
+
for supply in result:
|
|
159
|
+
assert supply.date_start <= datetime(2024, 6, 15) <= supply.date_end
|
|
160
|
+
|
|
161
|
+
@pytest.mark.asyncio
|
|
162
|
+
async def test_get_supply_stats(self, supply_service, sample_supplies):
|
|
163
|
+
"""Test getting supply statistics."""
|
|
164
|
+
# Setup mocks
|
|
165
|
+
supply_service._db_service.get_supplies.return_value = sample_supplies
|
|
166
|
+
|
|
167
|
+
# Execute
|
|
168
|
+
result = await supply_service.get_supply_stats()
|
|
169
|
+
|
|
170
|
+
# Verify
|
|
171
|
+
# Verify
|
|
172
|
+
assert result["total_supplies"] == 2
|
|
173
|
+
assert result["total_cups"] == 2
|
|
174
|
+
assert result["date_range"]["earliest_start"] == datetime(2023, 1, 1)
|
|
175
|
+
assert result["date_range"]["latest_end"] == datetime(2025, 6, 1)
|
|
176
|
+
assert result["point_types"] == {5: 1, 4: 1}
|
|
177
|
+
assert result["distributors"] == {
|
|
178
|
+
"Test Distributor 1": 1,
|
|
179
|
+
"Test Distributor 2": 1,
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
@pytest.mark.asyncio
|
|
183
|
+
async def test_validate_cups(self, supply_service, sample_supplies):
|
|
184
|
+
"""Test CUPS validation."""
|
|
185
|
+
# Setup mocks
|
|
186
|
+
supply_service._db_service.get_supplies.return_value = [sample_supplies[0]]
|
|
187
|
+
|
|
188
|
+
# Execute
|
|
189
|
+
result = await supply_service.validate_cups("ES001234567890123456AB")
|
|
190
|
+
|
|
191
|
+
# Verify
|
|
192
|
+
assert result is True
|
|
193
|
+
|
|
194
|
+
# Test invalid CUPS
|
|
195
|
+
supply_service._db_service.get_supplies.return_value = []
|
|
196
|
+
result = await supply_service.validate_cups("INVALID_CUPS")
|
|
197
|
+
assert result is False
|
|
198
|
+
|
|
199
|
+
@pytest.mark.asyncio
|
|
200
|
+
async def test_get_distributor_code(self, supply_service, sample_supplies):
|
|
201
|
+
"""Test getting distributor code."""
|
|
202
|
+
# Setup mocks
|
|
203
|
+
supply_service._db_service.get_supplies.return_value = [sample_supplies[0]]
|
|
204
|
+
|
|
205
|
+
# Execute
|
|
206
|
+
result = await supply_service.get_distributor_code("ES001234567890123456AB")
|
|
207
|
+
|
|
208
|
+
# Verify
|
|
209
|
+
assert result == "123"
|
|
210
|
+
|
|
211
|
+
@pytest.mark.asyncio
|
|
212
|
+
async def test_get_point_type(self, supply_service, sample_supplies):
|
|
213
|
+
"""Test getting point type."""
|
|
214
|
+
# Setup mocks
|
|
215
|
+
supply_service._db_service.get_supplies.return_value = [sample_supplies[0]]
|
|
216
|
+
|
|
217
|
+
# Execute
|
|
218
|
+
result = await supply_service.get_point_type("ES001234567890123456AB")
|
|
219
|
+
|
|
220
|
+
# Verify
|
|
221
|
+
assert result == 5
|
|
222
|
+
|
|
223
|
+
@pytest.mark.asyncio
|
|
224
|
+
async def test_update_supplies_no_data(self, supply_service):
|
|
225
|
+
"""Test supply update with no data returned."""
|
|
226
|
+
# Setup mocks
|
|
227
|
+
supply_service._datadis.get_supplies = AsyncMock(return_value=[])
|
|
228
|
+
|
|
229
|
+
# Execute
|
|
230
|
+
result = await supply_service.update_supplies()
|
|
231
|
+
|
|
232
|
+
# Verify
|
|
233
|
+
assert result["success"] is True
|
|
234
|
+
assert result["stats"]["fetched"] == 0
|
|
235
|
+
assert result["stats"]["saved"] == 0
|
|
236
|
+
|
|
237
|
+
@pytest.mark.asyncio
|
|
238
|
+
async def test_update_supplies_error(self, supply_service):
|
|
239
|
+
"""Test supply update with error."""
|
|
240
|
+
# Setup mocks
|
|
241
|
+
supply_service._datadis.get_supplies = AsyncMock(
|
|
242
|
+
side_effect=Exception("API Error")
|
|
243
|
+
)
|
|
244
|
+
|
|
245
|
+
# Execute
|
|
246
|
+
result = await supply_service.update_supplies()
|
|
247
|
+
|
|
248
|
+
# Verify
|
|
249
|
+
assert result["success"] is False
|
|
250
|
+
assert "error" in result
|
|
251
|
+
assert result["error"] == "API Error"
|