Advanced

Multi-Journal Accounting

In this tutorial, we will explore how to perform multiple-journal accounting using the Twisp Accounting Core.

Our primary focus will be on setting up a multi-journal ledger and posting various transactions across these journals to demonstrate how balances are materialized in accounts and account sets across journals.

We will walk through the following steps:

  1. Setup multiple journals and an account set in each journal
  2. Post transactions to each journal
  3. Query ledger entries across both journals

Step 1: Multi Journal Setup

We'll create two journals: "Journal 1" as the primary journal and "Journal 2" as the secondary journal.

Then, we'll create two account sets, one for each journal, both with a credit-normal balance type.

Next, create two accounts "Account A" and "Account B" and associate them with both account sets. Finally, create a transfer transaction code with the necessary parameters and transaction entries.

Setup Multi-Journal Ledger

mutation MultiJournalSetup {
  j1: createJournal(
    input: {
      journalId: "41ee64d6-dcde-46dc-bdc5-c9164517402a"
      name: "Journal 1"
      description: "Primary journal"
    }
  ) {
    journalId
  }

  j2: createJournal(
    input: {
      journalId: "2d9355ac-1844-4378-8fae-7ccb104e98c9"
      name: "Journal 2"
      description: "Secondary journal"
    }
  ) {
    journalId
  }

  acct_set_1: createAccountSet(
    input: {
      accountSetId: "861f2709-5e62-4a97-8364-b4d3b0a3b31f"
      journalId: "41ee64d6-dcde-46dc-bdc5-c9164517402a"
      name: "Accounts"
      description: "Group entries in all accounts for primary journal"
      normalBalanceType: CREDIT
    }
  ) {
    accountSetId
    normalBalanceType
  }

  acct_set_2: createAccountSet(
    input: {
      accountSetId: "c21f202f-d92d-48e5-aaf0-d48865a98051"
      journalId: "2d9355ac-1844-4378-8fae-7ccb104e98c9"
      name: "Accounts"
      description: "Group entries in all accounts for secondary journal"
      normalBalanceType: CREDIT
    }
  ) {
    accountSetId
    normalBalanceType
  }

  acct_a: createAccount(
    input: {
      accountId: "80c06296-7afb-4725-8cdd-57c2ce881af2"
      code: "ACCT_A"
      name: "Account A"
      description: "Account A"
      normalBalanceType: CREDIT
      status: ACTIVE
      accountSetIds: [
        "861f2709-5e62-4a97-8364-b4d3b0a3b31f"
        "c21f202f-d92d-48e5-aaf0-d48865a98051"
      ]
    }
  ) {
    accountId
    sets(first: 4) {
      nodes {
        accountSetId
        normalBalanceType
      }
    }
  }

  acct_b: createAccount(
    input: {
      accountId: "6d808949-437f-4f23-a345-b09225104808"
      code: "ACCT_B"
      name: "Account B"
      description: "Account B"
      normalBalanceType: CREDIT
      status: ACTIVE
      accountSetIds: [
        "861f2709-5e62-4a97-8364-b4d3b0a3b31f"
        "c21f202f-d92d-48e5-aaf0-d48865a98051"
      ]
    }
  ) {
    accountId
    sets(first: 4) {
      nodes {
        accountSetId
        normalBalanceType
      }
    }
  }

  xfr: createTranCode(
    input: {
      tranCodeId: "8f50f1be-a6c5-4f42-a623-57db9ff9f543"
      code: "XFR"
      description: "Transfer money."
      params: [
        { name: "effectiveDate", type: DATE }
        { name: "amount", type: DECIMAL }
        {
          name: "fromAccount"
          type: UUID
          description: "Account to send funds from."
        }
        {
          name: "toAccount"
          type: UUID
          description: "Recipient account. Required."
        }
        { name: "journal", type: UUID, description: "Journal ID. Required." }
      ]
      transaction: {
        journalId: "params.journal"
        effective: "params.effectiveDate"
      }
      entries: [
        {
          accountId: "params.fromAccount"
          units: "params.amount"
          currency: "'USD'"
          entryType: "'XFR_DR'"
          direction: "DEBIT"
          layer: "SETTLED"
        }
        {
          accountId: "params.toAccount"
          units: "params.amount"
          currency: "'USD'"
          entryType: "'XFR_CR'"
          direction: "CREDIT"
          layer: "SETTLED"
        }
      ]
    }
  ) {
    tranCodeId
  }
}

After completing this setup, our chart of accounts will look like this:

NameDescriptionNormal Balance TypeRecord Type
Account AAccount ACREDITAccount
Account BAccount BCREDITAccount
AccountsGroup entries in all accounts for the primary journalCREDITAccountSet
AccountsGroup entries in all accounts for the secondary journalCREDITAccountSet

We'll also have a simple XFR tran code for moving money between accounts.

Step 2: Post Transactions

Next, let's post two transactions using the XFR transaction code created above to write some entries to each journal.

In the first transaction, we'll move $11.33 from Account A to Account B in Journal 1. In the second transaction, we'll transfer $22.44 from Account B to Account A in Journal 2.

Post TXs to Each Journal

mutation PostTransactions {
  xfr_j1: postTransaction(
    input: {
      transactionId: "a3501651-3550-40a3-a5e4-a07d983348f8"
      tranCode: "XFR"
      params: {
        fromAccount: "80c06296-7afb-4725-8cdd-57c2ce881af2"
        toAccount: "6d808949-437f-4f23-a345-b09225104808"
        amount: "11.33"
        journal: "41ee64d6-dcde-46dc-bdc5-c9164517402a"
        effectiveDate: "2022-09-10"
      }
    }
  ) {
    transactionId
    entries(first: 10) {
      nodes {
        journalId
        accountId
        direction
        units
        currency
      }
    }
  }

  xfr_j2: postTransaction(
    input: {
      transactionId: "87e0c5f2-fc1e-4450-9129-aba1c00533c3"
      tranCode: "XFR"
      params: {
        fromAccount: "6d808949-437f-4f23-a345-b09225104808"
        toAccount: "80c06296-7afb-4725-8cdd-57c2ce881af2"
        amount: "22.44"
        journal: "2d9355ac-1844-4378-8fae-7ccb104e98c9"
        effectiveDate: "2022-09-11"
      }
    }
  ) {
    transactionId
    entries(first: 10) {
      nodes {
        journalId
        accountId
        direction
        units
        currency
      }
    }
  }
}

Step 3: Account Set Entries

Finally, let's investigate the entries written in each journal by the transactions posted.

We'll retrieve account sets 1 and 2 using their respective IDs. For each account set, we'll get the member accounts and entries. Also, we'll get the journals' balance (in USD).

Query Ledger Entries

query AccountSetEntries {
  acct_set_1: accountSet(id: "861f2709-5e62-4a97-8364-b4d3b0a3b31f") {
    members(first: 10) {
      nodes {
        ... on Account {
          accountId
        }
      }
    }
    entries(first: 20) {
      nodes {
        journalId
        accountId
        entryType
        layer
        direction
        units
        currency
      }
    }
    balance(currency: "USD") {
      journalId
      settled {
        normalBalance {
          units
        }
        drBalance {
          units
        }
        crBalance {
          units
        }
      }
    }
  }

  acct_set_2: accountSet(id: "c21f202f-d92d-48e5-aaf0-d48865a98051") {
    journalId
    members(first: 10) {
      nodes {
        ... on Account {
          accountId
        }
      }
    }
    entries(first: 20) {
      nodes {
        journalId
        accountId
        entryType
        layer
        direction
        units
        currency
      }
    }
    balance(currency: "USD") {
      journalId
      settled {
        normalBalance {
          units
        }
        drBalance {
          units
        }
        crBalance {
          units
        }
      }
    }
  }
}

For easier reading, here are the entries listed out:

TypeJournalAccountDirectionAmount
XFR_CRJournal 1Account BCREDIT$11.33
XFR_DRJournal 1Account ADEBIT$11.33
XFR_CRJournal 2Account ACREDIT$22.44
XFR_DRJournal 2Account BDEBIT$22.44

Summary

We began by establishing two separate journals and creating account sets and accounts for each. We then created a transfer transaction code that allowed us to post transactions across these journals. By posting two sample transactions, we illustrated how balances are materialized in accounts and account sets across different journals.

This tutorial provides a simplified into managing complex financial scenarios where multiple journals are required, such as consolidating the financial activity of multiple subsidiaries in a parent company or tracking transactions in various currencies.

Previous
Designing a Tran Code