Skip to content

Commit

Permalink
WIP
Browse files Browse the repository at this point in the history
  • Loading branch information
Iain-S committed Jul 10, 2024
1 parent 332feae commit c921f7d
Show file tree
Hide file tree
Showing 5 changed files with 63 additions and 28 deletions.
32 changes: 17 additions & 15 deletions rctab/routers/accounting/usage.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
import calendar
import datetime
import logging
from functools import reduce
from typing import Dict, List
from uuid import UUID

Expand Down Expand Up @@ -111,17 +112,21 @@ async def post_monthly_usage(

post_start = datetime.datetime.now()

date_min = datetime.date.today() + datetime.timedelta(days=4000)
date_max = datetime.date.today() - datetime.timedelta(days=4000)
monthly_usage = True
dates = sorted([x.date for x in all_usage.usage_list])
# if len(dates) == 0:
# raise HTTPException(
# status_code=400,
# detail="Post monthly usage data must have at least one record.",
# )
date_min = dates[-1]
date_max = dates[-0]

for usage in all_usage.usage_list:
if usage.date < date_min:
date_min = usage.date
if usage.date > date_max:
date_max = usage.date
if usage.monthly_upload is None:
monthly_usage = False
raise HTTPException(
status_code=400,
detail="Post monthly usage data must have the monthly_upload column populated.",
)

logger.info(
"Post monthly usage received data for %s - %s containing %d records",
Expand All @@ -133,13 +138,10 @@ async def post_monthly_usage(
if date_min.year != date_max.year or date_min.month != date_max.month:
raise HTTPException(
status_code=400,
detail=f"Post monthly usage data should contain usage only for one month. Min, Max usage date: ({str(date_min)}), ({str(date_max)}).",
)

if not monthly_usage:
raise HTTPException(
status_code=400,
detail="Post monthly usage data must have the monthly_upload column populated.",
detail=(
"Post monthly usage data should contain usage only for one month. "
f"Min, Max usage date: ({str(date_min)}), ({str(date_max)})."
),
)

month_start = datetime.date(date_min.year, date_min.month, 1)
Expand Down
15 changes: 10 additions & 5 deletions tests/data/example-monthly-wrong.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@
"publisher_type": "Azure",
"plan_name": null,
"charge_type": "Usage",
"frequency": "UsageBased"
"frequency": "UsageBased",
"monthly_upload": "2021-09-01"
},
{
"id": "/subscriptions/ce0f6ae0-2032-11ec-9621-0242ac130002/providers/Microsoft.Billing/billingPeriods/20210801/providers/Microsoft.Consumption/usageDetails/1538963a-0c4b-d98b-304b-3462b47dee3a",
Expand Down Expand Up @@ -93,7 +94,8 @@
"publisher_type": "Azure",
"plan_name": null,
"charge_type": "Usage",
"frequency": "UsageBased"
"frequency": "UsageBased",
"monthly_upload": "2021-09-01"
},
{
"id": "/subscriptions/ce0f6ae0-2032-11ec-9621-0242ac130002/providers/Microsoft.Billing/billingPeriods/20210801/providers/Microsoft.Consumption/usageDetails/a9fd329b-43ff-bc29-54ae-f3972876ed54",
Expand Down Expand Up @@ -141,7 +143,8 @@
"publisher_type": "Azure",
"plan_name": null,
"charge_type": "Usage",
"frequency": "UsageBased"
"frequency": "UsageBased",
"monthly_upload": "2021-09-01"
},
{
"id": "/subscriptions/ce0f6ae0-2032-11ec-9621-0242ac130002/providers/Microsoft.Billing/billingPeriods/20210901/providers/Microsoft.Consumption/usageDetails/0496ffbc-d5d9-a8f6-400d-4ba2c8286270",
Expand Down Expand Up @@ -189,7 +192,8 @@
"publisher_type": "Azure",
"plan_name": null,
"charge_type": "Usage",
"frequency": "UsageBased"
"frequency": "UsageBased",
"monthly_upload": "2021-09-01"
},
{
"id": "/subscriptions/ce0f6ae0-2032-11ec-9621-0242ac130002/providers/Microsoft.Billing/billingPeriods/20210901/providers/Microsoft.Consumption/usageDetails/f7b3299d-6379-8de3-3e27-fe03ec7fdb82",
Expand Down Expand Up @@ -237,6 +241,7 @@
"publisher_type": "Azure",
"plan_name": null,
"charge_type": "Usage",
"frequency": "UsageBased"
"frequency": "UsageBased",
"monthly_upload": "2021-09-01"
}
]
4 changes: 3 additions & 1 deletion tests/test_routes/test_finances.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,9 @@ def test_finance_route(auth_app: FastAPI) -> None:
result = client.request(
"GET",
PREFIX + "/finance",
content=SubscriptionItem(sub_id=UUID(int=33)).json(),
content=SubscriptionItem(sub_id=UUID(int=33))
.model_dump_json()
.encode("utf-8"),
)

assert result.status_code == 200
Expand Down
2 changes: 1 addition & 1 deletion tests/test_routes/test_status.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ def test_post_status(

resp = client.post(
"accounting/all-status",
content=all_status.json(),
content=all_status.model_dump_json().encode("utf-8"),
headers={"authorization": "Bearer " + token},
)
assert resp.status_code == 200
Expand Down
38 changes: 32 additions & 6 deletions tests/test_routes/test_usage.py
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def test_post_usage(

resp = client.post(
"usage/all-usage",
content=post_data.json(),
content=post_data.model_dump_json().encode("utf-8"),
headers={"authorization": "Bearer " + token},
)

Expand Down Expand Up @@ -221,7 +221,7 @@ def _post_costmanagement(
post_client = client.post(
"/usage/all-cm-usage",
headers={"authorization": "Bearer " + token},
content=all_usage.json(),
content=all_usage.model_dump_json().encode("utf-8"),
) # type: ignore
return post_client # type: ignore

Expand Down Expand Up @@ -298,25 +298,37 @@ def test_post_monthly_usage(
"rctab.routers.accounting.usage.refresh_desired_states", mock_refresh
)

# Should error if there is no data.
resp = client.post(
"usage/monthly-usage",
content=post_example_1_data.json(),
content=AllUsage.model_dump_json().encode("utf-8"),
headers={"authorization": "Bearer " + token},
)

assert resp.status_code == 400
assert "usage list is empty" in resp.text

resp = client.post(
"usage/monthly-usage",
content=post_example_2_data.json(),
content=post_example_1_data.model_dump_json().encode("utf-8"),
headers={"authorization": "Bearer " + token},
)

assert resp.status_code == 400
assert "should contain usage only for one month" in resp.text

resp = client.post(
"usage/monthly-usage",
content=post_example_3_data.json(),
content=post_example_2_data.model_dump_json().encode("utf-8"),
headers={"authorization": "Bearer " + token},
)

assert resp.status_code == 400
assert "data must have the monthly_upload column" in resp.text

resp = client.post(
"usage/monthly-usage",
content=post_example_3_data.model_dump_json().encode("utf-8"),
headers={"authorization": "Bearer " + token},
)

Expand All @@ -343,6 +355,20 @@ def test_post_monthly_usage(
)


@pytest.mark.asyncio
async def test_monthly_usage_dates(
test_db: Database, mocker: MockerFixture # pylint: disable=redefined-outer-name
) -> None:
mock_refresh = AsyncMock()
mocker.patch(
"rctab.routers.accounting.usage.refresh_materialised_view", mock_refresh
)

await post_usage(AllUsage(usage_list=[]), {"mock": "authentication"})

mock_refresh.assert_called_once_with(test_db, usage_view)


@pytest.mark.asyncio
async def test_post_usage_refreshes_view(
test_db: Database, mocker: MockerFixture # pylint: disable=redefined-outer-name
Expand Down Expand Up @@ -383,7 +409,7 @@ def test_post_usage_emails(

resp = client.post(
"usage/all-usage",
content=post_data.json(),
content=post_data.model_dump_json().encode("utf-8"),
headers={"authorization": "Bearer " + token},
)
assert resp.status_code == 200
Expand Down

0 comments on commit c921f7d

Please sign in to comment.