Transactions

A credit or debit from an Account is referred to as a Transaction, which has several metadata fields in our system, such as:

Transaction Fields

Name

Description

AllTransactionType (Enum)

0: Posted, 1: Memo, 2: Insufficient Funds

TransactionID

Unique identifier of the Transaction within this environment

HostAccountID

Which Account this Transaction relates to

OfxTrnType

ex: CREDIT

StatementDescription

ex. N9848 Q2 SOFTWAR DIR DEP 268904 10230 06/01/18

SignedTxnAmount

ex. -123.23

Note

For a more complete list, check out the sample response at GetAccountHistoryByIdWindowed module

Unlike Accounts, Transactions do not come in to your extension as part of the initial data blob from HQ. Rather, you will have to go back to the database for subsequent information. We did this in one way in the Online Banking Form Tutorial during the Using HQ API step. In that case we used the GetAccountHistoryById module. That HQ endpoint gave us ALL transactions for a given AccountId.

However, there are many endpoints that HQ provides for transaction search. For instance, if you are looking for only transactions that match a pattern, or just a subset of the entire transaction history, one such option is the GetAccountHistoryByIdWindowed module. This endpoint is more powerful, but also more complicated to call. Let’s check out an example:

from dataclasses import dataclass
from datetime import datetime, timedelta
from q2_sdk.core.http_handlers.tecton_server_handler import Q2TectonServerRequestHandler
from q2_sdk.hq.hq_api.q2_api import GetAccountHistoryByIdWindowed
from q2_sdk.hq.models.hq_response import HqResponse

# This is a neat way to consolidate all the input parameters and only
# pass a single argument to _get_windowed_transactions
@dataclass
class HistoryParameters:
    login_name: str
    host_account_id: str
    page_size: int = 100
    page_number: int = 1
    from_date: str = "1901-01-01"
    to_date: str = None

    @property
    def from_as_str(self) -> str:
        return self.from_date.strftime("%Y-%m-%d")

    @property
    def to_as_str(self) -> str:
        return self.to_date.strftime("%Y-%m-%d")


# This handler is missing lots of properties and such, meant only to show
# how this type of call might be constructed
class MyGetTransactionHandler(Q2TectonServerRequestHandler):

    async def default(self):
        from_date = datetime.today() - timedelta(days=365)  # Last 3 days
        history_parameters = HistoryParameters(
            'retail0',  # login_name
            5009,  # host_account_id
            from_date=from_date
        )
        hq_response = await self._get_windowed_transactions(history_parameters)
        data = {
            'transactions': []
        }
        if not hq_response.result_node.Data.AllHostTransactions.Transactions:
            data = 'No transactions for the given inputs'
        else:
            for tran in hq_response.result_node.Data.AllHostTransactions.Transactions:
                post_date = str(tran.PostDate)
                transaction_amount = tran.SignedTxnAmount.pyval
                data['transactions'].append(
                    {
                        'post_date': post_date,
                        'transaction_amount': transaction_amount
                    }
                )
        self.get_tecton_form('Transactions', )
        return self.get_tecton_form(
            "Transactions",
            custom_template=data,
            hide_submit_button=True
        )

    async def _get_windowed_transactions(self, history_parameters: HistoryParameters) -> HqResponse:
        get_account_history = GetAccountHistoryByIdWindowed.ParamsObj(
            self.logger,  # logger
            history_parameters.host_account_id,  # host_account_id
            history_parameters.page_size,  # page_size
            history_parameters.page_number,  # page_number
            True,  # perform_history_lookup
            False,  # perform_memo_lookup
            False,  # perform_nsf_lookup
            optional_filter=GetAccountHistoryByIdWindowed.OptionalFilter([
                GetAccountHistoryByIdWindowed.FilterItem(
                    0,  # is_or_operator_not_and
                    GetAccountHistoryByIdWindowed.Operand.GT,  # Operand
                    0,  # parens_before
                    0,  # parens_after
                    field_name="PostDate",
                    comparison_value=history_parameters.from_as_str
                ),
                GetAccountHistoryByIdWindowed.FilterItem(
                    0,  # is_or_operator_not_and
                    GetAccountHistoryByIdWindowed.Operand.LT,  # Operand
                    0,  # parens_before
                    0,  # parens_after
                    field_name="PostDate",
                    comparison_value=history_parameters.to_as_str
                )
            ]),
            optional_sort='',
            hq_credentials=self.hq_credentials
        )
        results = await GetAccountHistoryByIdWindowed.execute(get_account_history)
        return results

Assuming a database that has data for that account id (5009) and time range (365 days), the frontend will look something like this:

../../_images/frontend.png

Generated Vs Host Transactions

The Q2 database makes a distinction between Transactions originating from the Q2 system vs those we learn about by pulling from the Banking Core. Those that originate from Q2 (such as by using the Funds Transfer interface) are called Generated Transactions, living in the Q2_GeneratedTransaction table. Those that start in the Core (such as debit card purchases) are called Host Transactions, living in the Q2_HostTransactionHistory table. Generated Transactions also can have a subtype called a GT Flavor.