Over the past few months, multiple teams at Gusto have been rallying behind initiatives that help businesses navigate the uncertainties brought by the Coronavirus pandemic. Among these projects is the Paycheck Protection Program (PPP) loan forgiveness report. Through working on this report, we’ve come to respect the challenges involved in interpreting legislation, specifically the CARES Act and its ever-evolving guidances. In this post, we’d like to share how we translate legislation clauses into lines of code. We’ll dive into a few translation examples and discuss how we respond to changes to stay up to date with the latest guidances.
What is the PPP loan forgiveness?
As part of the CARES Act, the PPP loan is available to small and medium-size businesses (SMBs) for use toward eligible expenses, e.g. payrolls, rent, utilities, mortgage interests. At the end of the loan’s covered period, businesses can submit an application for forgiveness to waive up to the entire loan amount.
The PPP loan is a huge lifeline critical to the survival of many SMBs impacted by the pandemic. However, many SMBs don’t realize the stringent criteria required to meet full forgiveness eligibility. At a high level, the loan can be used to cover eligible expenses during an applicable period following the loan disbursement. During this period, at least 60% of the loan principal must be used toward payrolls. Additionally, employers are required to maintain both employee headcount and wages relative to baseline periods set by the law. Reductions in either headcount or wages could result in a lower forgiveness amount.
Gusto forgiveness report
Our goal was to build a report that allows customers to monitor how they track toward full forgiveness. Since virtually all forgiveness criteria rely on payroll data, Gusto, as their payroll provider, is in the best position to help customers accurately calculate their forgiveness status. Additionally, to keep the tool simple, wherever there are multiple options in the calculation we’ll calculate all possible permutations and select ones that yield the most optimal outcome.
While understanding the intricacies of our internal payroll system was central to this project, the most challenging aspect was the translation of legislation and interpreting ambiguous sections that come with it. We intentionally didn’t write any code in the first two days of the project. Instead, we dedicated our entire team’s effort to read and understand the Loan Forgiveness section of the CARES Act. We also held regular meetings with our internal legal and compliance team to help us navigate new concepts we didn’t initially grasp.
Our team discovered that the bill is structured very similarly to how we, as developers, write code. Clauses in the bill often make references to other sections. You’d have to jump through multiple sections to derive a full understanding of a sentence. In software development, these external references are simply function calls. We are trained to suspend our reading flow to dive deeper into another part of code as we inspect a specific class or method.
Let’s walk through a few examples to illustrate what we mean.
The translation process
In this section, we’ll walk through the first part of the forgiveness calculation, which deals with the headcount quotient calculation. This quotient measures the number of employees during the loan covered period compared to that of a baseline period. If an employer reduces their headcount during the covered period, their headcount quotient will be less, which results in a lower loan forgiveness amount.
The very first clause in the forgiveness calculation reads
AMOUNT MAY NOT EXCEED PRINCIPAL. — The amount of loan forgiveness under this section shall not exceed the principal amount of the financing made available under the applicable covered loan.
At the onset, this tells us that the loan amount is a user input to the report. We don’t know yet how to calculate the forgiveness amount, but we can translate this sentence into code as
The next section goes into more detailed instruction on how to calculate the quotient
(A) IN GENERAL. — The amount of loan forgiveness under this section shall be reduced, but not increased, by multiplying the amount described in subsection (b) by the quotient obtained by dividing —
(i) the average number of full-time equivalent employees per month employed by the eligible recipient during the covered period; by
(ii) (I) at the election of the borrower
(aa) the average number of full-time equivalent employees per month employed by the eligible recipient during the period beginning on February 15, 2019 and ending on June 30, 2019; or
(bb) the average number of full-time equivalent employees per month employed by the eligible recipient during the period beginning on January 1, 2020 and ending on February 29, 2020; or
As you can see, there are multiple references to sections that are either previously mentioned or will be subsequently defined. Let’s dissect these statements one by one.
Statement (A) instructs us to perform the multiplication below. You may notice it refers to the eligible loan amount described in a previous section and the quotient, which is defined in the next two subsections.
forgiveness_amount = loan_amount * quotient
We can also derive the headcount reduction, which is useful to present as a separate line item in the report summary
headcount_reduction = loan_amount * (1 — quotient)
In order to figure out the quotient, we first need to understand the calculation of the average full-time equivalent employees or FTEs. Lacking a formal definition specified in the CARES Act, we employed the Small Business Administration’s (SBA) definition of a full time employee in earlier legislations, which defines a full-time employee as someone who works 30+ hours per week. As an example, a company having one 40-hour/wk employee and three 15-hour/wk employees will have an FTE value of 2.5
Equipped with this knowledge, we can now write a helper method that calculates the total FTE as follow:
const DAYS_IN_WEEK = 7 const FULLTIME_THRESHOLD = 30 def calculate_fte(period) period_in_weeks = Integer(period.end - period.begin + 1.day) / DAYS_IN_WEEK total_fte = employees.sum do |employee| avg_hrs_per_week = work_hours_for(employee, period) / period_in_weeks # Ensures that each employee can only equate to 1 max FTE. [avg_hrs_per_week / FULLTIME_THRESHOLD, 1].min end end
This is a great example that illustrates how ambiguity in legislation can lead to very different interpretations. As we shall see, the SBA’s subsequent guidance introduces two different approaches to calculate the FTE, both of which differ slightly from our initial interpretation. Fortunately, we can simply swap out the above helper to support the SBA’s new approach.
The quotient can now be obtained by dividing the FTEs in the covered period (i) by the baseline FTEs in a selected lookback period (ii). We'll need to prevent division by 0 for companies that do not have FTEs during the lookback period.
def quotient calculate_fte(covered_period) / calculate_fte(lookback_period) end
The covered period is dependent on the loan disbursement date, which we require users to enter in order to generate their report. The covered period’s duration was originally specified as the 8 weeks following the loan disbursement in the CARES Act. It was subsequently updated to 24 weeks by the PPP Flexibility Act. For the lookback period, employers have a few options depending on whether their business is seasonal or not. Rather than requiring users to make this selection, we calculate all possible options and automatically choose the most optimal that produces the best forgiveness outcome.
We hope that the above translation steps give you a better understanding of our process. The complete forgiveness calculation includes two additional components, wages reduction and payroll cost, which we won’t cover in this post.
Responding to evolving guidances
Since launch, our forgiveness report has been used by over 30,000 companies, cumulatively tracking over $2.4 billion in PPP loan. We worked hard to ensure that our customers had the forgiveness report as early as possible, and vetted our report with dozens of lenders to ensure that it was consistent with how the lenders, who are responsible for processing millions of forgiveness applications, were interpreting the SBA and Treasury requirements. We also pulled together a working group of over 75 companies across the payroll industry, lending industry, and accounting community to ensure that our industries were aligned in providing useful forgiveness reports for small businesses
Over the past five months, the SBA and Treasury have released more than 15 interim final rules, FAQs, and interpretations of the CARES Act. An example of such changes is the SBA guideline for filing the loan forgiveness application released on May 15th, 2020. This guideline deviated significantly from instructions laid out in the CARES Act in several key areas.
In terms of FTE calculations, the SBA introduced two new methods, which we’ll refer to as simplified and granular. The simplified method assigns an FTE of 1.0 for all employees who work 40 hours or more per week and 0.5 for those who work fewer hours. The granular method is similar to our previous implementation but with a full-time threshold of 40 hours/week instead of 30 hours/week. Supporting more options means that we have to double our calculations to cover all possible permutations. However, the gain in simplifying the customer experience still outweighs the time added to perform the extra calculations. In general, we found that the simplified method tends to work well for employers who have mostly part-time employees whereas the granular works best for those who employ mostly full-time employees.
The new guidance also introduced a Safe Harbor clause, which clarifies details about the rehire exemption mentioned in the CARES Act. The CARES Act alludes to the possibility for removing the headcount reduction if the employer is able to recover all their headcount by 6/30/2020. The new guidance provided more details, specifically the criteria for exemption eligibility and the baseline comparison periods.
The biggest highlight of this SBA guidance was its resolution of a confusing clause in the CARES Act that requires employers to compare total wages in the 8-week covered period against those of a full quarter. Employers were understandably frustrated when they discovered that in order to attain full forgiveness they had to increase wages for applicable employees by approximately 20%. Under the new guidance, annual rates are used for salaried employees and hourly rates for hourly employees. This change effectively normalized the different lengths of the two periods. Therefore, wage reduction only kicks in once an employer actually reduces her team pay rates beyond 25%.
From a product standpoint, the SBA guidance should be treated as a brand new report. However, our initial decision to organize the core calculations into three distinct modules, headcount, wages, and payroll cost, really pays off. It allowed us to retain most of the structure in the original code and gave us the flexibility to adapt minimal code changes to applicable modules. We released the modifications to support the SBA guidance shortly after its release.
Multiple major changes were also introduced following the SBA guidance, including the Paycheck Protection Program Flexibility Act. This new legislation extended the cover period from 8 to 24 weeks and reduced the payroll threshold from 75% to 60%. We were able to quickly adapt and incrementally incorporate these updates into our report.
While it was frustrating for us to deal with ambiguous and changing requirements throughout this project, we’ve gained a lot of respect for the challenges faced by SMBs during this time of uncertainty. It must be extremely difficult for employers to balance between keeping their businesses afloat while navigating changing guidances that directly affect their livelihood and those of their employees. It is a huge motivator for us to keep our report accurate with the latest guidances. Because removing this extra work on the customers' part means they’ll have more time to dedicate to their team and business needs.
Thanks to Jeanette Quick, Ngan Pham, Jesse Zhou, and Ben Zhang for providing feedback on earlier drafts.