|
1 | 1 | from datetime import date |
2 | 2 | from decimal import Decimal |
| 3 | +from unittest.mock import patch |
3 | 4 |
|
4 | 5 | import pytest |
5 | 6 |
|
6 | 7 | from models import ( |
| 8 | + CAN, |
7 | 9 | AgreementType, |
8 | 10 | BudgetLineItemStatus, |
| 11 | + CANFundingBudget, |
| 12 | + CANFundingDetails, |
9 | 13 | ContractAgreement, |
10 | 14 | ContractBudgetLineItem, |
11 | 15 | GrantAgreement, |
12 | 16 | GrantBudgetLineItem, |
| 17 | + Portfolio, |
| 18 | + ResearchProject, |
13 | 19 | ) |
14 | 20 | from ops_api.ops.utils.reporting_summary import get_reporting_counts |
15 | 21 |
|
@@ -202,3 +208,132 @@ def test_get_reporting_counts_empty_fy(app, loaded_db, app_ctx): |
202 | 208 | assert result["new_agreements"]["total"] == 0 |
203 | 209 | assert result["continuing_agreements"]["total"] == 0 |
204 | 210 | assert result["budget_lines"]["total"] == 0 |
| 211 | + |
| 212 | + |
| 213 | +@pytest.fixture() |
| 214 | +def db_with_2024_data(app, loaded_db, app_ctx): |
| 215 | + """Fixture with FY 2024 data for testing with mocked get_current_fiscal_year.""" |
| 216 | + |
| 217 | + portfolio = Portfolio(name="FY2024 TEST PORTFOLIO", division_id=1) |
| 218 | + can = CAN(number="FY2024_TEST_CAN") |
| 219 | + portfolio.cans.append(can) |
| 220 | + loaded_db.add(portfolio) |
| 221 | + loaded_db.commit() |
| 222 | + |
| 223 | + can_funding_details = CANFundingDetails(fiscal_year=2024, fund_code="FY2024TEST") |
| 224 | + can.funding_details = can_funding_details |
| 225 | + loaded_db.add(can_funding_details) |
| 226 | + loaded_db.commit() |
| 227 | + |
| 228 | + can_funding_budget = CANFundingBudget(can_id=can.id, fiscal_year=2024, budget=Decimal(30000000)) |
| 229 | + loaded_db.add(can_funding_budget) |
| 230 | + loaded_db.commit() |
| 231 | + |
| 232 | + # Research project |
| 233 | + project = ResearchProject(title="FY2024 Test Project", short_title="FY24TP", description="Test project for FY 2024") |
| 234 | + loaded_db.add(project) |
| 235 | + loaded_db.commit() |
| 236 | + |
| 237 | + # Contract agreement with PLANNED BLI in FY 2024 |
| 238 | + contract = ContractAgreement(name="FY2024 Contract", agreement_type=AgreementType.CONTRACT, project_id=project.id) |
| 239 | + loaded_db.add(contract) |
| 240 | + loaded_db.commit() |
| 241 | + |
| 242 | + bli_planned = ContractBudgetLineItem( |
| 243 | + line_description="FY2024 Planned BLI", |
| 244 | + amount=Decimal("8000000"), |
| 245 | + status=BudgetLineItemStatus.PLANNED, |
| 246 | + can_id=can.id, |
| 247 | + date_needed=date(2024, 3, 15), |
| 248 | + agreement_id=contract.id, |
| 249 | + ) |
| 250 | + loaded_db.add(bli_planned) |
| 251 | + loaded_db.commit() |
| 252 | + |
| 253 | + # Grant agreement with OBLIGATED BLI in FY 2024 |
| 254 | + grant = GrantAgreement(name="FY2024 Grant", agreement_type=AgreementType.GRANT, project_id=project.id) |
| 255 | + loaded_db.add(grant) |
| 256 | + loaded_db.commit() |
| 257 | + |
| 258 | + bli_obligated = GrantBudgetLineItem( |
| 259 | + line_description="FY2024 Obligated BLI", |
| 260 | + amount=Decimal("3000000"), |
| 261 | + status=BudgetLineItemStatus.OBLIGATED, |
| 262 | + can_id=can.id, |
| 263 | + date_needed=date(2024, 8, 1), |
| 264 | + agreement_id=grant.id, |
| 265 | + ) |
| 266 | + loaded_db.add(bli_obligated) |
| 267 | + loaded_db.commit() |
| 268 | + |
| 269 | + # Contract with IN_EXECUTION BLI in FY 2024 |
| 270 | + contract_exec = ContractAgreement( |
| 271 | + name="FY2024 Executing Contract", agreement_type=AgreementType.CONTRACT, project_id=project.id |
| 272 | + ) |
| 273 | + loaded_db.add(contract_exec) |
| 274 | + loaded_db.commit() |
| 275 | + |
| 276 | + bli_in_execution = ContractBudgetLineItem( |
| 277 | + line_description="FY2024 In Execution BLI", |
| 278 | + amount=Decimal("2000000"), |
| 279 | + status=BudgetLineItemStatus.IN_EXECUTION, |
| 280 | + can_id=can.id, |
| 281 | + date_needed=date(2024, 5, 1), |
| 282 | + agreement_id=contract_exec.id, |
| 283 | + ) |
| 284 | + loaded_db.add(bli_in_execution) |
| 285 | + loaded_db.commit() |
| 286 | + |
| 287 | + yield loaded_db |
| 288 | + |
| 289 | + loaded_db.rollback() |
| 290 | + for obj in [ |
| 291 | + bli_in_execution, |
| 292 | + contract_exec, |
| 293 | + bli_obligated, |
| 294 | + grant, |
| 295 | + bli_planned, |
| 296 | + contract, |
| 297 | + project, |
| 298 | + can_funding_budget, |
| 299 | + can_funding_details, |
| 300 | + can, |
| 301 | + portfolio, |
| 302 | + ]: |
| 303 | + loaded_db.delete(obj) |
| 304 | + loaded_db.commit() |
| 305 | + |
| 306 | + |
| 307 | +@patch("models.utils.fiscal_year.get_current_fiscal_year", return_value=2024) |
| 308 | +def test_get_reporting_counts_with_mocked_fy_2024(mock_fy, app, db_with_2024_data, app_ctx): |
| 309 | + """Test get_reporting_counts with mocked get_current_fiscal_year returning 2024.""" |
| 310 | + # Verify the mock is working |
| 311 | + # assert get_current_fiscal_year() == 2024 |
| 312 | + |
| 313 | + # Get reporting counts for FY 2024 |
| 314 | + result = get_reporting_counts(app.db_session, 2024) |
| 315 | + |
| 316 | + # Verify structure |
| 317 | + assert "projects" in result |
| 318 | + assert "agreements" in result |
| 319 | + assert "new_agreements" in result |
| 320 | + assert "continuing_agreements" in result |
| 321 | + assert "budget_lines" in result |
| 322 | + |
| 323 | + # Verify project counts - we created 1 research project |
| 324 | + assert result["projects"]["total"] >= 1 |
| 325 | + project_types = {t["type"]: t["count"] for t in result["projects"]["types"]} |
| 326 | + assert project_types.get("RESEARCH", 0) >= 1 |
| 327 | + |
| 328 | + # Verify agreement counts - we created 2 contracts and 1 grant with non-DRAFT BLIs |
| 329 | + assert result["agreements"]["total"] >= 3 |
| 330 | + agreement_types = {t["type"]: t["count"] for t in result["agreements"]["types"]} |
| 331 | + assert agreement_types.get("CONTRACT", 0) >= 2 # 2 contracts |
| 332 | + assert agreement_types.get("GRANT", 0) >= 1 # 1 grant |
| 333 | + |
| 334 | + # Verify budget line counts - we created 3 BLIs: PLANNED, OBLIGATED, IN_EXECUTION |
| 335 | + assert result["budget_lines"]["total"] >= 3 |
| 336 | + bli_types = {t["type"]: t["count"] for t in result["budget_lines"]["types"]} |
| 337 | + assert bli_types.get("PLANNED", 0) >= 1 |
| 338 | + assert bli_types.get("OBLIGATED", 0) >= 1 |
| 339 | + assert bli_types.get("IN_EXECUTION", 0) >= 1 |
0 commit comments