Twisp 101

Step 4: Organize Accounts for Balance Rollups

Use account sets to group and organize accounts into a chart, taking advantage of the built-in balance aggregations.

With AccountSets, we can collect related accounts to provide an easy interface into summary balances and queries into the entries.

We've already created checking accounts for each customer, but Zuzu also needs a way to summarize all customer accounts so that we can see the total balance.

To accomplish this, we'll create an account set called "Customers" and add the customer accounts to it.

Create customers account set

010_CreateCustomersAccountSet

mutation CreateCustomersAccountSet($customersId: UUID!, $journalId: UUID!) {
  createAccountSet(
    input: {
      accountSetId: $customersId
      journalId: $journalId
      name: "Customers"
      description: "All customer's accounts"
      normalBalanceType: CREDIT
    }
  ) {
    accountSetId
    journalId
    name
    description
    normalBalanceType
  }
}

Now that we have an account set, let's add the two customer accounts to it:

011_AddCustomersToSet

mutation AddCustomersToSet(
  $customersId: UUID!
  $ernieId: UUID!
  $bertId: UUID!
) {
  addErnie: addToAccountSet(
    id: $customersId
    member: { memberType: ACCOUNT, memberId: $ernieId }
  ) {
    accountSetId
  }

  addBert: addToAccountSet(
    id: $customersId
    member: { memberType: ACCOUNT, memberId: $bertId }
  ) {
    accountSetId
  }
}

Now that we have posted several transactions and created an account set, we can look at balances and interrogate their history to see how account balances change with each activity posted to that account.

Review balances & interrogate history

Let's start by querying for the balance of the "Customers" set, as well as the balance of each member account.

013_GetCustomersBalances

query GetCustomersBalances($customersId: UUID!, $journalId: UUID!) {
  accountSet(id: $customersId) {
    name
    balance {
      settled {
        normalBalance {
          units
        }
      }
    }
    members(first: 10) {
      nodes {
        __typename
        ... on Account {
          name
          balance(journalId: $journalId) {
            settled {
              normalBalance {
                units
              }
            }
          }
        }
      }
    }
  }
}

As expected, the account set's balance is always equal to the sum of its member's balances.

Because records in Twisp are append-only, we can review the history of any record to see how its state changed over time.

Let's query the balance history of Ernie's account and compare it to the entries to see how it changed in response to transactions posted.

014_GetErnieBalanceHistory

query GetErnieBalanceHistory($ernieId: UUID!, $journalId: UUID!) {
  account(id: $ernieId) {
    name
    balance(journalId: $journalId) {
      settled {
        normalBalance {
          units
        }
      }
      version
      history(first: 10) {
        nodes {
          version
          settled {
            normalBalance {
              units
            }
          }
        }
      }
    }
    entries(
      where: { journalId: { eq: "822cb59f-ce51-4837-8391-2af3b7a5fc51" } }
      first: 10
    ) {
      nodes {
        entryType
        direction
        units
      }
    }
  }
}

Conclusion

That finalizes the tutorial! Let's recap what we did to customize and test an accounting core for the imaginary neobank Zuzu:

  • ✅ Modeled accounts for customers, assets, and revenue
  • ✅ Designed tran codes for bank transfers as well as ACH credits and debits
  • ✅ Organized customer accounts into a set and ran queries against it
  • ✅ Interrogated the balance history and entries for an account

We hope that this has been useful for you to understand how Twisp works and what you can build with it. Obviously, this is an oversimplified example. Your product will certainly be more complex (and interesting)!

We'd love to talk with you about your project. If you're interested, please get in touch.

Previous
Model Intra-Bank Transfers