M Group Ledger Entries#

A Ledger Entry Group is a collection of related Ledger Entries that occur at different points in time. Each Group tracks the net change to each Ledger Account balance it affects.

Use Ledger Entry Groups to tie together Ledger Entries that are part of the same funds flow, such as a deposit, settlement or invoice. To store metadata, use tags instead.

a. Configuring Groups

#

Groups for a Ledger Entry Type are defined as a list of key/value pairs in the Schema:

Ledger Entry Type with Groups
{
  "type": "user_initiates_withdrawal",
  "description": "{{user_id}} initiates withdrawal",
  "lines": [
    {
      "account": {
        "path": "liabilities/users:{{user_id}}/available"
      },
      "key": "decrease_user_balance",
      "amount": "-{{withdraw_amount}}"
    },
    {...other line}
  ],
  "groups": [
    {
      "key": "withdrawal",
      "value": "{{withdrawal_id}}"
    }
  ]
}

Ledger Entry Groups have the following limitations:

  • You can specify up to 10 Groups for any Ledger Entry type.
  • Parameters can be used in the value of a Group, but not the key.
  • Group keys must be unique per Ledger Entry, and you can only provide one value for each key.

b. Querying balances

#

Use the ledgerEntryGroup.balances expansion to get the net change per Ledger Account balance from all Ledger Entries in a Group. Group balances are eventually consistent.

GetLedgerEntryGroupBalances
query GetLedgerEntryGroupBalances(
  $ledger: LedgerMatchInput!
  $entryGroup: EntryGroupMatchInput!,
) {
  ledger(ledger: $ledger) {
    ledgerEntryGroup(ledgerEntryGroup: $entryGroup) {
      balances {
        nodes {
          account {
            path
          }
          ownBalance
        }
      }
    }
  }
}
GetLedgerEntryGroupBalances Variables
{
  "entryGroup": {
    "key": "withdrawal",
    "value": "some-withdrawal-id"
  },
  "ledger": {
    "ik": "quickstart-ledger"
  }
}

The response for a Ledger Entry Group with a settled withdrawal:

GetLedgerEntryGroupBalances Response
{
  "data": {
    "ledger": {
      "ledgerEntryGroup": {
        "balances": {
          "nodes": [
            {
              "account": {
                "path": "asset-root/bank"
              },
              "ownBalance": "-50000"
            },
            {
              "account": {
                "path": "liability-root/user:user-id/available"
              },
              "ownBalance": "-50000"
            },
            {
              "account": {
                "path": "liability-root/user:user-id/pending"
              },
              "ownBalance": "0"
            }
          ]
        }
      }
    }
  }
}
Consistent balances#

Ledger Entry Groups support strongly-consistent reads for the ownBalance field. See Consistent Ledger Entry Group balances for more information on how to configure this in your Schema. See Query Consistent Groups for how to query strongly consistent Ledger Entry Group balances.

Filtering balances#

Balances in a Group may be filtered by account, currency, and ownBalance.

QueryLedgerEntryGroupBalances
query QueryLedgerEntryGroupBalances(
  $ledger: LedgerMatchInput!
  $entryGroup: EntryGroupMatchInput!,
  $filter: LedgerEntryGroupBalanceFilterSet,
) {
  ledger(ledger: $ledger) {
    ledgerEntryGroup(ledgerEntryGroup: $entryGroup) {
      balances(filter: $filter) {
        nodes {
          account {
            path
          }
          ownBalance
          currency {
            code
          }
        }
      }
    }
  }
}
QueryLedgerEntryGroupBalances Variables
{
  "entryGroup": {
    "key": "withdrawal",
    "value": "12345"
  },
  "ledger": {
    "ik": "quickstart-ledger"
  },
  "filter": {
    "currency": {
      "equalTo": { "code": "USD" }
    },
    "ownBalance": {
      "gte": "-1000",
      "lte": "1000"
    },
    "account": {
      "path": {
        "equalTo": "liability-root/user:user-id/pending"
      }
    }
  }
}

The response is:

QueryLedgerEntryGroupBalances Response
{
  "data": {
    "ledger": {
      "ledgerEntryGroup": {
        "balances": {
          "nodes": [
            {
              "account": {
                "path": "liability-root/user:user-id/pending"
              },
              "ownBalance": "0",
              "currency": {
                "code": "USD"
              }
            }
          ]
        }
      }
    }
  }
}
Filter by template#

Group balances support filtering account paths using '*' in place of a template variable.

QueryLedgerEntryGroupBalances
query QueryLedgerEntryGroupBalances(
  $ledger: LedgerMatchInput!
  $entryGroup: EntryGroupMatchInput!,
  $filter: LedgerEntryGroupBalanceFilterSet,
) {
  ledger(ledger: $ledger) {
    ledgerEntryGroup(ledgerEntryGroup: $entryGroup) {
      balances(filter: $filter) {
        nodes {
          account {
            path
          }
          ownBalance
        }
      }
    }
  }
}
QueryLedgerEntryGroupBalances Variables
{
  "entryGroup": {
    "key": "withdrawal",
    "value": "12345"
  },
  "ledger": {
    "ik": "quickstart-ledger"
  },
  "filter": {
    "account": {
      "path": {
        "matches": "liability-root/user:*/pending"
      }
    }
  }
}

The response is:

QueryLedgerEntryGroupBalances Response
{
  "data": {
    "ledger": {
      "ledgerEntryGroup": {
        "balances": {
          "nodes": [
            {
              "account": {
                "path": "liability-root/user:user-id/pending"
              },
              "ownBalance": "0"
            },
            {
              "account": {
                "path": "liability-root/user:another-user-id/pending"
              },
              "ownBalance": "2500"
            }
          ]
        }
      }
    }
  }
}

c. Updating Entry Groups

#

In addition to Groups defined in your Schema, you can add a posted Ledger Entry to additional Groups.

updateLedgerEntry mutation
mutation UpdateLedgerEntryGroups(
  $ledgerEntry: LedgerEntryMatchInput!
  $update: UpdateLedgerEntryInput!
) {
  updateLedgerEntry(
    ledgerEntry: $ledgerEntry,
    update: $update
  ) {
    __typename
    ... on UpdateLedgerEntryResult {
      entry {
        type
        ik
        groups {
          key
          value
        }
        lines {
          nodes {
            amount
            description
            account {
              path
            }
          }
        }
      }
    }
    ... on Error {
      code
      message
    }
  }
}
 
updateLedgerEntry variables to add and update groups
{
  "ledgerEntry": {
    "ik": "add-ledger-entry",
    "ledger": {
      "ik": "quickstart-ledger"
    }
  },
  "update": {
    "groups": [
      {
        "key": "withdrawal",
        "value": "12345"
      }
    ]
  }
}

This is an additive operation:

  • If you specify a new Group, this Ledger Entry will be added to that Group
  • If you don't specify an existing Group, this Ledger Entry will remain in that Group
  • You may not modify an existing Group key or remove an Ledger Entry from a Group

You can only update a Ledger Entry a maximum of 10 times.