# Step 3: Model Intra-Bank Transfers

Zuzu also needs to support bank transfers between customer accounts so that customers can send money to one another.

Source: https://www.twisp.com/docs/tutorials/twisp-101/step-3

This type of transaction we'll model with a tran code called `BANK_TRANSFER`, but it's going to be a little more complex than the previous one.

Zuzu isn't just letting customers transfer money for free, all day long. Instead, they'll charge a small percentage fee of 1% with a $10 maximum, paid by the sender.

## Create a revenue account

The fee charged for a bank transfer will be represented as a `DEBIT` against the sender's bank account. The balancing `CREDIT` entry will be posted to Zuzu's revenue account, which doesn't exist yet.

To support bank transfers, then, we'll need to first create the revenue account for Zuzu.

**Request**

```graphql
mutation CreateRevenueAccount($revenueId: UUID!) {
  createAccount(
    input: {
      accountId: $revenueId
      name: "Revenues"
      code: "REV"
      description: "Company revenues (e.g. fees)"
      normalBalanceType: CREDIT
    }
  ) {
    accountId
    name
  }
}
```
**Response**

```json
{
  "data": {
    "createAccount": {
      "accountId": "ece5e752-5445-4f4e-8861-d09c5c417061",
      "name": "Revenues"
    }
  }
}
```
**Variables**

```json
{
  "revenueId": "ece5e752-5445-4f4e-8861-d09c5c417061"
}
```

Now that we have the revenue account, we can design the tran code for internal transfers.

## Define the TranCode for transfers

The tran code for this transaction type needs to do a few things:

- Write entries to move the defined amount from the sender's checking account to the receiver's checking account
- Write an additional two entries to move the fee from the sender's checking account to the Revenue account, using a runtime expression to calculate the fee amount

When posting a transaction, we want to enable the poster to provide the **sender's** account ID, the **receiver's** account ID, the **amount** to transfer, the 1% **fee**, and the **effective date** of the transfer. We'll define each of these as `params` on the TranCode.

**Request**

```graphql
mutation CreateBankTransferTranCode($transferId: UUID!) {
  createTranCode(
    input: {
      tranCodeId: $transferId
      code: "BANK_TRANSFER"
      description: "Transfer $ internally from one checking account to another. The sender is charged a 1% fee or $10, whichever is smaller."
      params: [
        { name: "fromAccount", type: UUID, description: "Sender's account ID." }
        { name: "toAccount", type: UUID, description: "Receiver's account ID." }
        {
          name: "amount"
          type: DECIMAL
          description: "Amount with decimal, e.g. `1.23`."
        }
        {
          name: "fee"
          type: DECIMAL
          description: "Transfer fee as decimal percentage, e.g. `0.01` for 1%"
        }
        {
          name: "effective"
          type: DATE
          description: "Effective date for transaction."
        }
      ]
      transaction: {
        journalId: "uuid('822cb59f-ce51-4837-8391-2af3b7a5fc51')"
        effective: "params.effective"
      }
      entries: [
        {
          accountId: "uuid(params.fromAccount)"
          units: "params.amount"
          currency: "'USD'"
          entryType: "'TRANSFER_DR'"
          direction: "DEBIT"
          layer: "SETTLED"
        }
        {
          accountId: "uuid(params.toAccount)"
          units: "params.amount"
          currency: "'USD'"
          entryType: "'TRANSFER_CR'"
          direction: "CREDIT"
          layer: "SETTLED"
        }
        {
          accountId: "uuid(params.fromAccount)"
          units: "decimal.Round(decimal.Mul(params.amount, params.fee), 'half_up', 2)"
          currency: "'USD'"
          entryType: "'TRANSFER_FEE_DR'"
          direction: "DEBIT"
          layer: "SETTLED"
        }
        {
          accountId: "uuid('ece5e752-5445-4f4e-8861-d09c5c417061')" # This is the account ID for the Revenues account
          units: "decimal.Round(decimal.Mul(params.amount, params.fee), 'half_up', 2)"
          currency: "'USD'"
          entryType: "'TRANSFER_FEE_CR'"
          direction: "CREDIT"
          layer: "SETTLED"
        }
      ]
    }
  ) {
    tranCodeId
  }
}
```
**Response**

```json
{
  "data": {
    "createTranCode": {
      "tranCodeId": "a0d9e35a-1df6-4f22-8e39-15c72e60b2d5"
    }
  }
}
```
**Variables**

```json
{
  "transferId": "a0d9e35a-1df6-4f22-8e39-15c72e60b2d5"
}
```

> **Tip:**
>
> Writing clear descriptions for tran codes and their parameters is a great way to help API users can understand what the tran code is for and how to invoke it.

## Post a test transaction

Let's test this transaction out by sending $2.25 from Ernie to Bert. To see the results of the transaction as encoded by the tran code, we'll return the entries posted, digging all the way down into the account for each entry.

**Request**

```graphql
mutation PostBankTransfer {
  postTransaction(
    input: {
      transactionId: "9c328550-bba3-423b-a58a-b3f9786a80ae"
      tranCode: "BANK_TRANSFER"
      params: {
        fromAccount: "1fd1dd3e-33fe-4ef5-9d58-676ef8d306b5"
        toAccount: "6c6affb0-5cf5-402b-8d84-01bfc1624a2c"
        amount: "2.25"
        fee: "0.02"
        effective: "2022-09-10"
      }
    }
  ) {
    transactionId
    entries(first: 10) {
      nodes {
        units
        direction
        entryType
        account {
          name
        }
      }
    }
  }
}
```
**Response**

```json
{
  "data": {
    "postTransaction": {
      "transactionId": "9c328550-bba3-423b-a58a-b3f9786a80ae",
      "entries": {
        "nodes": [
          {
            "units": "2.25",
            "direction": "DEBIT",
            "entryType": "TRANSFER_DR",
            "account": {
              "name": "Ernie Bishop - Checking"
            }
          },
          {
            "units": "2.25",
            "direction": "CREDIT",
            "entryType": "TRANSFER_CR",
            "account": {
              "name": "Bert - Checking"
            }
          },
          {
            "units": "0.05",
            "direction": "DEBIT",
            "entryType": "TRANSFER_FEE_DR",
            "account": {
              "name": "Ernie Bishop - Checking"
            }
          },
          {
            "units": "0.05",
            "direction": "CREDIT",
            "entryType": "TRANSFER_FEE_CR",
            "account": {
              "name": "Revenues"
            }
          }
        ]
      }
    }
  }
}
```

Success! From our response, we can see that each entry was posted to the correct account and for the correct amount.
