def validate_date_range_is_within_a_financial_year(start_date, end_date): try: start_date = datetime.strptime(start_date, "%Y-%m-%d").date() end_date = datetime.strptime(end_date, "%Y-%m-%d").date() except ValueError: raise InvalidRequest(message="Input must be a date in the format: YYYY-MM-DD", status_code=400) if end_date < start_date: raise InvalidRequest(message="Start date must be before end date", status_code=400) start_fy = get_financial_year_for_datetime(get_local_timezone_midnight_in_utc(start_date)) end_fy = get_financial_year_for_datetime(get_local_timezone_midnight_in_utc(end_date)) if start_fy != end_fy: raise InvalidRequest(message="Date must be in a single financial year.", status_code=400) return start_date, end_date
def fetch_sms_free_allowance_remainder(start_date): # ASSUMPTION: AnnualBilling has been populated for year. billing_year = get_financial_year_for_datetime(start_date) start_of_year = date(billing_year, 4, 1) billable_units = func.coalesce( func.sum(FactBilling.billable_units * FactBilling.rate_multiplier), 0) query = db.session.query( AnnualBilling.service_id.label("service_id"), AnnualBilling.free_sms_fragment_limit, billable_units.label('billable_units'), func.greatest((AnnualBilling.free_sms_fragment_limit - billable_units).cast(Integer), 0).label('sms_remainder') ).outerjoin( # if there are no ft_billing rows for a service we still want to return the annual billing so we can use the # free_sms_fragment_limit) FactBilling, and_( AnnualBilling.service_id == FactBilling.service_id, FactBilling.bst_date >= start_of_year, FactBilling.bst_date < start_date, FactBilling.notification_type == SMS_TYPE, )).filter( AnnualBilling.financial_year_start == billing_year, ).group_by( AnnualBilling.service_id, AnnualBilling.free_sms_fragment_limit, ) return query
def test_get_financial_year_for_datetime(dt, fy): assert get_financial_year_for_datetime(dt) == fy