Calculator

Keep Your Budgets Flexible With Configurable Budget Periods

TL;DR – Automation makes managing budgets easier and the Budget API now supports configurable budget time periods for even more flexibility!

Even though we just walked through some of the basics of using the Budget API, there’s a new feature that’s worth checking out: the ability to set custom time periods on budgets. Here’s a refresher on how budgets work if you’d like one. By default, budgets work on a monthly basis, so they reset on the first of each month. This is pretty convenient for most use cases, but might not work for you if your finances work on different periods. Regardless of what your timing needs are, let’s look at two new ways to work with your budgets!

Calendar periods

With this new update, you can change the general time period that a budget looks at. There are three options here:

  • Monthly: the default for budgets, starting on the first day of each month and ending on the last day of each month (January 1st through January 31st, for example)
  • Quarterly: an even split of the year into four quarters starting on January 1st, April 1st, July 1st, and October 1st
  • Yearly: the whole year, starting with January 1st

Since budgets are typically repeated, these new options give you additional options for what the time period should look like. Each budget has its own period that it covers, so you can mix budgets of different time periods together for more customizable reporting!

These time periods also affect the budget amounts (more info under the Amount section here) if you’re using the dynamic “last period’s spend” rather than a fixed amount. So, if you’re working with a quarterly budget and it’s currently Q2 (April 1 – June 30th), the last period’s spend amount would be based on Q1 (January 1st – March 31st). This works the same way for yearly budgets, so you can easily track your spending year over year. Let’s see what this looks like using the API!

Here’s our new function for creating a budget (and here’s a link to the documentation if you want to see more information about the different properties):

def create_budget(name: str, amount: int = 0, dynamic_amount: bool = False,
 cal_period = budgets.CalendarPeriod.MONTH,
 custom_start: date_pb2.Date = {}, custom_end: date_pb2.Date = {}):
 """
 Creates a budget using the API
 Args:
 name (str):
   Required. The display name for the budget
 amount (int):
   Optional. The fixed amount that this budget will compare spend against
 dynamic_amount (bool):
   Optional. If True, the amount arg will be ignored and this budget will
   compare spend to whatever spend occurred in the last period
 cal_period (google.cloud.billing.budgets.CalendarPeriod):
   Optional. ENUM to customize the calendar period of this budget. Defaults to
   monthly. If False, custom_period will be used instead
 custom_start (date_pb2.Date):
   Optional. If cal_period is False and a custom_start is present, the budget
   will use a custom period rather than a calendar period. This will be the
   start of the custom period
 custom_end (date_pb2.Date):
   Optional. If the budget is using a custom period, this will be the end date
   of the custom period. If no end date is specified, the budget will measure
   spend starting from the start date and without any end date
 """
 new_amount = budgets.BudgetAmount()
 # Choosing between a fixed amount or the dynamic amount
 if dynamic_amount:
   new_amount.last_period_amount = budgets.LastPeriodAmount()
 else:
   new_amount.specified_amount = {'units': amount}
 new_budget_details = budgets.Budget({
   'display_name': name,
   'amount': new_amount,
 })
 new_filter = budgets.Filter()
 # Choosing between a calendar period or a custom period
 if cal_period != False:
   new_filter.calendar_period = cal_period
 elif custom_start:
   new_filter.custom_period = {
     'start_date': custom_start
   }
   if custom_end:
     new_filter.custom_period.end_date = custom_end
 new_budget_details.budget_filter = new_filter
 # Create the budget
 new_budget = client.create_budget(request = {
   'parent': BILLING_ACCOUNT,
   'budget': new_budget_details
 })
 print(f'Created budget: {new_budget.display_name}')

Adding a calendar period is pretty straightforward, since it’s just passing an ENUM into the budget filter. Here’s the part where the filter is set:

new_filter = budgets.Filter()
 # Choosing between a calendar period or a custom period
 if cal_period != False:
   new_filter.calendar_period = cal_period

and

new_budget_details.budget_filter = new_filter
 # Create the budget
 new_budget = client.create_budget(request = {
   'parent': BILLING_ACCOUNT,
   'budget': new_budget_details
 })

Now we can pass in budgets.CalendarPeriod.MONTH (or .YEAR or .QUARTER) in order to set the calendar period for this budget. We’ve also updated the function that lists budgets to include more information about the budget, so if we create a new budget and list it:

create_budget("Yearly Budget", 200, False, budgets.CalendarPeriod.YEAR)
list_budgets()

The output will look like this:

Name: Yearly Budget
Specified Amount: 200 USD
Budget calendar period: Every year

Custom periods

Picking the calendar periods is great, but what if you need something a bit more custom? For example, maybe you want to set a budget for that ever-popular holiday season, or for a week where you’re rolling out a new product? Custom periods (as the name might imply) can help you with those by giving you the option to set custom start and end dates. So if you’re rolling out that new product on August 18th, you could create a budget with a start date of 2021-08-15 and an end date of 2021-08-25 (or whatever else you want) to track spending during just that period. Combined with all the other filters, there’s quite a bit of granularity!

These custom period budgets work a bit differently than the typical calendar period budgets, though:

  • Custom period budgets do not repeat. These budgets are only useful for the time period specified so you’ll have to create multiple budgets to cover each of the time periods you want to know more about
  • Since they don’t repeat, you can’t use the “last period’s spend” setting for amount, which makes sense because there’s no last period!
  • The start date must be after January 1st 2017. I’m not really sure who this would affect but now you know
  • And the end date is actually optional. If you don’t provide one, the budget will track all the usage after the start date with no end in sight

With all of that out of the way, let’s look at how to actually create these custom period budgets! The same create_budget function works, and here’s the part that actually sets the start and end dates:

# Choosing between a calendar period or a custom period
 if cal_period != False:
   new_filter.calendar_period = cal_period
 elif custom_start:
   new_filter.custom_period = {
     'start_date': custom_start
   }
   if custom_end:
     new_filter.custom_period.end_date = custom_end

Since a budget can’t have a calendar period and a custom period, this will create the budget with one or the other and pass in the properties through the budget filter. So when we run the code:

custom_start_date = {
 'year': 2021,
 'month': 12,
 'day': 20
}
custom_end_date = {
 'year': 2021,
 'month': 12,
 'day': 31
}
create_budget("Christmas Budget", 150, False, False, custom_start_date, custom_end_date)
list_budgets()

The output will be:

Name: Christmas Budget
Specified Amount: 150 USD
Custom budget period start: 2021-12-20
Custom budget period end: 2021-12-31

One more thing

It’s worth noting that any budgets created with a custom time period won’t show up in the UI. For now, these budgets will have to be managed through the API only. This code should hopefully help you get started with managing them and getting ready for when they’ll be available in the console at some point in the near futureTM. Also here’s the updated list_budget code:

def list_budgets():
 """
 Print out the details of all the budgets for the specified billing account
 """
 all_budgets = client.list_budgets(request = {'parent': BILLING_ACCOUNT})
 print('Budget summary')
 print('--------------')
 for budget in all_budgets:
   print(f'Name: {budget.display_name}')
   # Specified or dynamic amount
   b_amount = budget.amount
   if 'specified_amount' in b_amount:
     print(f'Specified Amount: {b_amount.specified_amount.units} '
           f'{b_amount.specified_amount.currency_code}')
   if 'last_period_amount' in b_amount:
     print('Dynamic spend (based on last period)')
   # Calendar period or custom period
   b_filter = budget.budget_filter
   if 'calendar_period' in b_filter:
     print(f'Budget calendar period: Every '
           f'{(budgets.CalendarPeriod(b_filter.calendar_period).name).lower()}')
   if 'custom_period' in b_filter:
     b_start = b_filter.custom_period.start_date
     print(f'Custom budget period start: '
           f'{b_start.year}-{b_start.month}-{b_start.day}')
     if 'end_date' in b_filter.custom_period:
       b_end = b_filter.custom_period.end_date
       print(f'Custom budget period end: {b_end.year}-{b_end.month}-{b_end.day}')
   print('')

In the meantime, you can check out the client library and the documentation for more details. Happy budgeting!

By: Mark Mirchandani (Google Cloud Developer Advocate) and Alex Lucas (Google Cloud Developer Advocate)
Source: Google Cloud Blog

Total
0
Shares
Leave a Reply
Previous Article
Google Cloud | Anthos

Anthos In Depth: All The Posts In Our Hybrid And Multicloud Development Series

Next Article

Google Cloud 2021 Summits Kicking Off With Data Cloud Summit This Week

Related Posts