{% extends "ui/templates/base/layout.html" %} {% block content %}

Accounting · Bank Reconciliation

Bank Reconciliation

Compare normalized Bank Analyzer transactions with Tally Bank ledgers. Phase 20 remembers each client bank-account ↔ Tally-ledger mapping, can reconcile every mapped account in one action, supports wider cheque/clearing timing windows, and keeps reviewer resolutions. Tally access remains read-only.

{% if message %}
{{ message }}
{% endif %} {% if error %}
{{ error }}
{% endif %}
{% if selected_client and selected_tally_guid %}

1. Select the Bank Analyzer job

Choose the completed client-bound analysis whose imported bank transactions you want to reconcile. The job can contain any number of bank accounts.

{% if selected_job_id %}

2. Map client bank accounts to Tally Bank ledgers

Mappings are remembered client-wise and company-wise. Once all accounts are mapped, future reconciliation runs do not require selecting the bank ledger again.

{% for account in source_accounts %} {% set existing = namespace(value=None) %} {% for mapping in bank_mappings %} {% if mapping.account_number == account.account_number %}{% set existing.value = mapping %}{% endif %} {% endfor %}
{% for company in companies %}{% if company.guid==selected_tally_guid %}{% endif %}{% endfor %}
Statement account
{{ account.bank_name or 'Bank' }} · {{ account.account_number }}
{{ account.transaction_count }} imported transaction(s)
{% else %}
No imported bank accounts were found for this job. Ensure its Accounting import status is Completed.
{% endfor %}

3. Reconcile mapped bank accounts

Use a wider timing tolerance for cheque issue/presentation or deposit/clearing differences. Amount and bank direction must still match exactly before the engine considers a Tally voucher as a candidate.

{% for company in companies %}{% if company.guid==selected_tally_guid %}{% endif %}{% endfor %}
Run one account manually
{% for company in companies %}{% if company.guid==selected_tally_guid %}{% endif %}{% endfor %}
{% endif %} {% endif %} {% if selected_client %}

Recent Reconciliation Runs

Runs preserve their results and never modify Tally.

{% for run in runs %} {% set summary = run.summary_json|default('{}') %} {% else %} {% endfor %}
RunBank / AccountPeriodStatusResult
#{{ run.id }}
{{ run.bank_ledger_name }}
{{ run.account_number or "All imported accounts" }}
{{ run.date_from }} → {{ run.date_to }} {{ run.status|replace('_',' ')|title }}{% if run.last_error %}
{{ run.last_error }}
{% endif %}
{% set s = run_summaries.get(run.id, {}) %} {% if run.status=='completed' %}
Matched {{ s.get('matched',0) }} · Probable {{ s.get('probable_match',0) }} · Timing {{ s.get('timing_difference',0) }}
Bank only {{ s.get('bank_only',0) }} · Books only {{ s.get('books_only',0) }} · Duplicate {{ s.get('duplicate_candidate',0) }}
Unreconciled net difference ₹{{ '%.2f'|format(s.get('unreconciled_net_difference',0)) }}
{% else %}—{% endif %}
Open
No reconciliation runs yet.
{% endif %} {% if selected_run %}

Run #{{ selected_run.id }} · {{ selected_run.bank_ledger_name }}

{{ selected_run.date_from }} → {{ selected_run.date_to }} · Status {{ selected_run.status|replace('_',' ')|title }}

{% if selected_run.status=='completed' %}
{% endif %}
{% if selected_run.status in ['queued','extracting'] %}
The connected Local Agent is reading Tally vouchers. Refresh this page shortly.
{% elif selected_run.status=='failed' %}
{{ selected_run.last_error }}
{% elif selected_run.status=='completed' %} {% set rs = run_summaries.get(selected_run.id, {}) %}
Matched
{{ rs.get('matched',0) }}
Probable
{{ rs.get('probable_match',0) }}
Timing differences
{{ rs.get('timing_difference',0) }}
Bank only
{{ rs.get('bank_only',0) }}
Dr ₹{{ '%.2f'|format(rs.get('bank_only_debit_amount',0)) }} · Cr ₹{{ '%.2f'|format(rs.get('bank_only_credit_amount',0)) }}
Books only
{{ rs.get('books_only',0) }}
Dr ₹{{ '%.2f'|format(rs.get('books_only_debit_amount',0)) }} · Cr ₹{{ '%.2f'|format(rs.get('books_only_credit_amount',0)) }}
Unreconciled net
₹{{ '%.2f'|format(rs.get('unreconciled_net_difference',0)) }}
Tolerance {{ rs.get('date_tolerance_days',15) }} days
{% for item in items %} {% else %} {% endfor %}
ResultBank StatementTallyWhyAction
{{ item.match_status|replace('_',' ')|title }} {% if item.confidence %}
{{ item.confidence }}%
{% endif %}
{% if item.bank_transaction_id %}
{{ item.bank_date }} · {{ item.bank_direction }} · ₹{{ '%.2f'|format(item.bank_amount) }}
{{ item.bank_reference or '-' }}
{{ item.bank_narration }}
{% else %}—{% endif %}
{% if item.tally_voucher_number or item.tally_guid %}
{{ item.tally_date }} · {{ item.tally_voucher_type }} · ₹{{ '%.2f'|format(item.tally_amount) }}
Voucher {{ item.tally_voucher_number or item.tally_guid }}
{{ item.tally_reference or '-' }}
{{ item.tally_narration }}
{% else %}—{% endif %}
{{ item.match_reason }} {% if item.resolution_status and item.resolution_status != 'unresolved' %}
Reviewed: {{ item.resolution_status|replace('_',' ')|title }}{% if item.resolution_note %}
{{ item.resolution_note }}
{% endif %}
{% endif %}
{% if item.match_status=='bank_only' and item.bank_transaction_id %} Open Accounting Queue {% endif %}
No reconciliation rows for this filter.
{% endif %}
{% endif %}
{% endblock %}