Skip to content

Commit c5a8f7d

Browse files
authored
Merge pull request #48 from alan-turing-institute/monthly-upload
Monthly upload
2 parents f9fd821 + 0c45817 commit c5a8f7d

File tree

8 files changed

+159
-352
lines changed

8 files changed

+159
-352
lines changed

rctab/routers/accounting/usage.py

+34-73
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
"""Set and get usage data."""
22

3-
import calendar
43
import datetime
54
import logging
65
from typing import Dict, List
@@ -109,19 +108,24 @@ async def post_monthly_usage(
109108
"""Inserts monthly usage data into the database."""
110109
logger.info("Post monthly usage called")
111110

112-
post_start = datetime.datetime.now()
111+
if len(all_usage.usage_list) == 0:
112+
raise HTTPException(
113+
status_code=400,
114+
detail="Monthly usage data must have at least one record.",
115+
)
113116

114-
date_min = datetime.date.today() + datetime.timedelta(days=4000)
115-
date_max = datetime.date.today() - datetime.timedelta(days=4000)
116-
monthly_usage = True
117+
post_start = datetime.datetime.now()
117118

118119
for usage in all_usage.usage_list:
119-
if usage.date < date_min:
120-
date_min = usage.date
121-
if usage.date > date_max:
122-
date_max = usage.date
123120
if usage.monthly_upload is None:
124-
monthly_usage = False
121+
raise HTTPException(
122+
status_code=400,
123+
detail="Post monthly usage data must have the monthly_upload column populated.",
124+
)
125+
126+
dates = sorted([x.date for x in all_usage.usage_list])
127+
date_min = dates[0]
128+
date_max = dates[-1]
125129

126130
logger.info(
127131
"Post monthly usage received data for %s - %s containing %d records",
@@ -130,79 +134,36 @@ async def post_monthly_usage(
130134
len(all_usage.usage_list),
131135
)
132136

133-
if date_min.year != date_max.year or date_min.month != date_max.month:
134-
raise HTTPException(
135-
status_code=400,
136-
detail=f"Post monthly usage data should contain usage only for one month. Min, Max usage date: ({str(date_min)}), ({str(date_max)}).",
137-
)
137+
async with database.transaction():
138138

139-
if not monthly_usage:
140-
raise HTTPException(
141-
status_code=400,
142-
detail="Post monthly usage data must have the monthly_upload column populated.",
139+
logger.info(
140+
"Post monthly usage deleting existing usage data for %s - %s",
141+
date_min,
142+
date_max,
143143
)
144144

145-
month_start = datetime.date(date_min.year, date_min.month, 1)
146-
month_end = datetime.date(
147-
date_min.year,
148-
date_min.month,
149-
calendar.monthrange(date_min.year, date_min.month)[1],
150-
)
151-
152-
logger.info(
153-
"Post monthly usage checks if data for %s - %s has already been posted",
154-
month_start,
155-
month_end,
156-
)
157-
158-
# Check if monthly usage has already been posted for the month
159-
query = select([accounting_models.usage])
160-
query = query.where(accounting_models.usage.c.date >= month_start)
161-
query = query.where(accounting_models.usage.c.date <= month_end)
162-
query = query.where(accounting_models.usage.c.monthly_upload.isnot(None))
163-
164-
query_result = await database.fetch_all(query)
165-
166-
if query_result is not None and len(query_result) > 0:
167-
raise HTTPException(
168-
status_code=400,
169-
detail=f"Post monthly usage data for {str(month_start)}-{str(month_end)} has already been posted.",
145+
# Delete all usage for the time period to have a blank slate.
146+
query_del = (
147+
accounting_models.usage.delete()
148+
.where(accounting_models.usage.c.date >= date_min)
149+
.where(accounting_models.usage.c.date <= date_max)
170150
)
151+
await database.execute(query_del)
171152

172-
async with UsageEmailContextManager(database):
173-
174-
async with database.transaction():
175-
176-
logger.info(
177-
"Post monthly usage deleting existing usage data for %s - %s",
178-
month_start,
179-
month_end,
180-
)
181-
182-
# delete al the usage for the month
183-
query_del = accounting_models.usage.delete().where(
184-
accounting_models.usage.c.date >= month_start
185-
)
186-
query_del = query_del.where(accounting_models.usage.c.date <= month_end)
187-
await database.execute(query_del)
188-
189-
logger.info(
190-
"Post monthly usage inserting new subscriptions if they don't exist"
191-
)
192-
193-
unique_subscriptions = list(
194-
{i.subscription_id for i in all_usage.usage_list}
195-
)
153+
logger.info(
154+
"Post monthly usage inserting new subscriptions if they don't exist"
155+
)
196156

197-
await insert_subscriptions_if_not_exists(unique_subscriptions)
157+
unique_subscriptions = list({i.subscription_id for i in all_usage.usage_list})
198158

199-
logger.info("Post monthly usage inserting monthly usage data")
159+
await insert_subscriptions_if_not_exists(unique_subscriptions)
200160

201-
await insert_usage(all_usage)
161+
logger.info("Post monthly usage inserting monthly usage data")
202162

203-
logger.info("Post monthly usage refreshing desired states")
163+
await insert_usage(all_usage)
204164

205-
await refresh_desired_states(UUID(ADMIN_OID), unique_subscriptions)
165+
# Note that we don't refresh the desired states here as we don't
166+
# want to trigger excess emails.
206167

207168
logger.info("Post monthly usage data took %s", datetime.datetime.now() - post_start)
208169

tests/data/example-monthly-wrong.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -206,7 +206,7 @@
206206
"account_name": "JDoe",
207207
"subscription_id": "ce0f6ae0-2032-11ec-9621-0242ac130002",
208208
"subscription_name": "JDoe",
209-
"date": "2021-10-01",
209+
"date": "2021-09-30",
210210
"product": "Azure Defender for Resource Manager - Standard - Events",
211211
"part_number": "AAH-05467",
212212
"meter_id": "f71b1ea3-c809-4ecb-b9d9-ae6b6fa67bd3",

tests/data/example-monthly-wrong2.json

-242
This file was deleted.

0 commit comments

Comments
 (0)