mirror of
https://github.com/GSA/notifications-api.git
synced 2026-09-05 23:38:25 -04:00
use dates rather than datetimes when comparing with bst_date
bst_date is a date field. Comparing dates with datetimes in postgres gets confusing and dangerous. See this example, where a date evaluates as older than midnight that same day. ``` notification_api=# select '2019-04-01' >= '2019-04-01 00:00'; ?column? ---------- f (1 row) ``` By only using dates everywhere, we reduce the chance of these bugs happening
This commit is contained in:
@@ -1,4 +1,4 @@
|
|||||||
from datetime import datetime, timedelta
|
from datetime import datetime, timedelta, date, time
|
||||||
|
|
||||||
from notifications_utils.timezones import convert_bst_to_utc
|
from notifications_utils.timezones import convert_bst_to_utc
|
||||||
import pytz
|
import pytz
|
||||||
@@ -64,6 +64,9 @@ def get_current_financial_year_start_year():
|
|||||||
|
|
||||||
|
|
||||||
def get_financial_year_for_datetime(start_date):
|
def get_financial_year_for_datetime(start_date):
|
||||||
|
if type(start_date) == date:
|
||||||
|
start_date = datetime.combine(start_date, time.min)
|
||||||
|
|
||||||
year = int(start_date.strftime('%Y'))
|
year = int(start_date.strftime('%Y'))
|
||||||
if start_date < get_april_fools(year):
|
if start_date < get_april_fools(year):
|
||||||
return year - 1
|
return year - 1
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from datetime import datetime, timedelta, time
|
from datetime import datetime, timedelta, time, date
|
||||||
|
|
||||||
from flask import current_app
|
from flask import current_app
|
||||||
from notifications_utils.timezones import convert_bst_to_utc, convert_utc_to_bst
|
from notifications_utils.timezones import convert_bst_to_utc, convert_utc_to_bst
|
||||||
@@ -7,7 +7,6 @@ from sqlalchemy import func, case, desc, Date, Integer, and_
|
|||||||
|
|
||||||
from app import db
|
from app import db
|
||||||
from app.dao.date_util import (
|
from app.dao.date_util import (
|
||||||
get_april_fools as financial_year_start,
|
|
||||||
get_financial_year,
|
get_financial_year,
|
||||||
get_financial_year_for_datetime
|
get_financial_year_for_datetime
|
||||||
)
|
)
|
||||||
@@ -34,7 +33,7 @@ from app.utils import get_london_midnight_in_utc
|
|||||||
def fetch_sms_free_allowance_remainder(start_date):
|
def fetch_sms_free_allowance_remainder(start_date):
|
||||||
# ASSUMPTION: AnnualBilling has been populated for year.
|
# ASSUMPTION: AnnualBilling has been populated for year.
|
||||||
billing_year = get_financial_year_for_datetime(start_date)
|
billing_year = get_financial_year_for_datetime(start_date)
|
||||||
start_of_year = convert_utc_to_bst(financial_year_start(billing_year))
|
start_of_year = date(billing_year, 4, 1)
|
||||||
|
|
||||||
billable_units = func.coalesce(func.sum(FactBilling.billable_units * FactBilling.rate_multiplier), 0)
|
billable_units = func.coalesce(func.sum(FactBilling.billable_units * FactBilling.rate_multiplier), 0)
|
||||||
|
|
||||||
|
|||||||
@@ -50,15 +50,15 @@ def validate_date_range_is_within_a_financial_year(start_date, end_date):
|
|||||||
if start_fy != end_fy:
|
if start_fy != end_fy:
|
||||||
raise InvalidRequest(message="Date must be in a single financial year.", status_code=400)
|
raise InvalidRequest(message="Date must be in a single financial year.", status_code=400)
|
||||||
|
|
||||||
|
return start_date, end_date
|
||||||
|
|
||||||
|
|
||||||
@platform_stats_blueprint.route('usage-for-all-services')
|
@platform_stats_blueprint.route('usage-for-all-services')
|
||||||
def get_usage_for_all_services():
|
def get_usage_for_all_services():
|
||||||
start_date = request.args.get('start_date')
|
start_date = request.args.get('start_date')
|
||||||
end_date = request.args.get('end_date')
|
end_date = request.args.get('end_date')
|
||||||
|
|
||||||
validate_date_range_is_within_a_financial_year(start_date, end_date)
|
start_date, end_date = validate_date_range_is_within_a_financial_year(start_date, end_date)
|
||||||
start_date = datetime.strptime(start_date, "%Y-%m-%d")
|
|
||||||
end_date = datetime.strptime(end_date, "%Y-%m-%d")
|
|
||||||
|
|
||||||
sms_costs = fetch_sms_billing_for_all_services(start_date, end_date)
|
sms_costs = fetch_sms_billing_for_all_services(start_date, end_date)
|
||||||
letter_costs = fetch_letter_costs_for_all_services(start_date, end_date)
|
letter_costs = fetch_letter_costs_for_all_services(start_date, end_date)
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
from datetime import datetime
|
from datetime import datetime, date
|
||||||
|
|
||||||
import pytest
|
import pytest
|
||||||
|
|
||||||
@@ -40,7 +40,8 @@ def test_get_month_start_and_end_date_in_utc(month, year, expected_start, expect
|
|||||||
(datetime(2018, 3, 31, 23, 0, 0), 2018),
|
(datetime(2018, 3, 31, 23, 0, 0), 2018),
|
||||||
(datetime(2019, 3, 31, 22, 59, 59), 2018),
|
(datetime(2019, 3, 31, 22, 59, 59), 2018),
|
||||||
(datetime(2019, 3, 31, 23, 0, 0), 2019),
|
(datetime(2019, 3, 31, 23, 0, 0), 2019),
|
||||||
(datetime(2020, 3, 31, 22, 59, 0), 2019),
|
(date(2019, 3, 31), 2018),
|
||||||
|
(date(2019, 4, 1), 2019),
|
||||||
])
|
])
|
||||||
def test_get_financial_year_for_datetime(dt, fy):
|
def test_get_financial_year_for_datetime(dt, fy):
|
||||||
assert get_financial_year_for_datetime(dt) == fy
|
assert get_financial_year_for_datetime(dt) == fy
|
||||||
|
|||||||
Reference in New Issue
Block a user