Files
arrr-erp/app/modules/accounting/templates/accounting/automatic_voucher_sources.html
T
2026-08-23 18:45:21 +05:30

245 lines
15 KiB
HTML

{% extends "ui/templates/base/layout.html" %}
{% block content %}
<div class="space-y-6">
<div class="flex flex-wrap items-start justify-between gap-3">
<div>
<p class="text-xs font-semibold uppercase tracking-[0.16em] text-brand-600">Accounting Engine · Phase 18</p>
<h1 class="mt-1 text-2xl font-semibold text-slate-900">Automatic Accounting Preparation</h1>
<p class="mt-1 max-w-5xl text-sm text-slate-500">
Create native Tally voucher drafts automatically from existing Bank Analyzer and E-Way Bill source data. Purchase and Sales drafts retain stock-item level quantity, unit, rate, HSN and taxable value for native Tally inventory vouchers.
</p>
</div>
<div class="flex flex-wrap gap-2">
<a href="/tools/accounting/voucher-engine{% if selected_client %}?client_id={{ selected_client.id }}{% endif %}" class="rounded-xl border border-slate-300 bg-white px-4 py-2 text-sm font-semibold">Voucher Review Queue</a>
<a href="/tools/accounting/chart-of-accounts{% if selected_client %}?client_id={{ selected_client.id }}{% endif %}" class="rounded-xl border border-slate-300 bg-white px-4 py-2 text-sm font-semibold">Chart of Accounts</a>
</div>
</div>
{% if message %}<div class="rounded-xl border border-emerald-200 bg-emerald-50 p-3 text-sm text-emerald-800">{{ message }}</div>{% endif %}
{% if error %}<div class="rounded-xl border border-red-200 bg-red-50 p-3 text-sm text-red-800">{{ error }}</div>{% endif %}
<section class="rounded-2xl bg-white p-5 shadow-soft">
<form method="get" class="grid gap-4 md:grid-cols-2 xl:grid-cols-6">
<label class="text-xs font-semibold xl:col-span-2">ERP Client
<select name="client_id" required class="mt-1 w-full rounded-lg border border-slate-300 bg-white px-3 py-2">
<option value="">Select client</option>
{% for c in clients %}
<option value="{{ c.id }}" {% if selected_client and selected_client.id==c.id %}selected{% endif %}>{{ c.client_name }}</option>
{% endfor %}
</select>
</label>
<label class="text-xs font-semibold xl:col-span-2">Tally Company / Chart of Accounts
<select name="tally_guid" class="mt-1 w-full rounded-lg border border-slate-300 bg-white px-3 py-2">
<option value="">Select company</option>
{% for c in company_options %}
<option value="{{ c.guid }}" {% if selected_tally_guid==c.guid %}selected{% endif %}>{{ c.name }}</option>
{% endfor %}
</select>
</label>
<label class="text-xs font-semibold">From
<input type="date" name="from_date" value="{{ from_date }}" class="mt-1 w-full rounded-lg border border-slate-300 px-3 py-2">
</label>
<label class="text-xs font-semibold">To
<input type="date" name="to_date" value="{{ to_date }}" class="mt-1 w-full rounded-lg border border-slate-300 px-3 py-2">
</label>
<div class="xl:col-span-6 flex justify-end">
<button class="rounded-xl bg-brand-600 px-5 py-2 text-sm font-semibold text-white">Load Automatic Sources</button>
</div>
</form>
</section>
{% if selected_client and selected_tally_guid %}
<section class="grid gap-4 lg:grid-cols-3">
<div class="rounded-2xl border border-emerald-200 bg-emerald-50/50 p-5">
<p class="text-xs font-semibold uppercase tracking-wider text-emerald-700">Bank Statements</p>
<h2 class="mt-1 font-semibold">Receipt / Payment / Contra</h2>
<p class="mt-1 text-sm text-slate-600">Bank Analyzer rows are converted into native Receipt, Payment or Contra voucher drafts. The bank ledger is chosen from the client's classified Chart of Accounts.</p>
</div>
<div class="rounded-2xl border border-blue-200 bg-blue-50/50 p-5">
<p class="text-xs font-semibold uppercase tracking-wider text-blue-700">E-Way Bill · Inward</p>
<h2 class="mt-1 font-semibold">Stock-item Purchase</h2>
<p class="mt-1 text-sm text-slate-600">Each invoice retains every item, HSN, quantity, unit, rate, taxable value and tax amounts and creates a native Purchase voucher draft.</p>
</div>
<div class="rounded-2xl border border-violet-200 bg-violet-50/50 p-5">
<p class="text-xs font-semibold uppercase tracking-wider text-violet-700">E-Way Bill · Outward</p>
<h2 class="mt-1 font-semibold">Stock-item Sales</h2>
<p class="mt-1 text-sm text-slate-600">Outward invoices create native Sales voucher drafts with item-wise inventory allocations and output-tax ledger lines.</p>
</div>
</section>
<section class="rounded-2xl bg-white shadow-soft">
<div class="flex flex-wrap items-center justify-between gap-3 border-b border-slate-200 p-5">
<div>
<h2 class="font-semibold">Bank Analyzer Transactions</h2>
<p class="text-sm text-slate-500">One click creates the proposed Receipt / Payment / Contra draft. Posting remains subject to the common review and Tally preflight controls.</p>
</div>
<form method="get" class="flex flex-wrap gap-2">
<input type="hidden" name="client_id" value="{{ selected_client.id }}">
<input type="hidden" name="tally_guid" value="{{ selected_tally_guid }}">
<input type="hidden" name="from_date" value="{{ from_date }}">
<input type="hidden" name="to_date" value="{{ to_date }}">
<select name="bank_source" class="rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm">
{% for source in sources.bank %}
<option value="{{ source.table_name }}" {% if selected_bank_source==source.table_name %}selected{% endif %}>{{ source.table_name }}</option>
{% endfor %}
</select>
<button class="rounded-lg border border-slate-300 px-3 py-2 text-sm font-semibold">Change Source</button>
</form>
</div>
{% if not sources.bank %}
<div class="p-8 text-center text-slate-500">
No existing Bank Analyzer transaction table containing client/date/narration/amount fields was discovered in the current ERP schema. Existing Bank Analyzer data has not been changed.
</div>
{% elif not bank_rows %}
<div class="p-8 text-center text-slate-500">No Bank Analyzer transactions were found for the selected client/period.</div>
{% else %}
<div class="overflow-x-auto">
<table class="min-w-full text-sm">
<thead>
<tr class="bg-slate-50 text-left text-xs uppercase text-slate-500">
<th class="px-4 py-3">Date</th>
<th class="px-4 py-3">Narration / Party</th>
<th class="px-4 py-3">Direction</th>
<th class="px-4 py-3 text-right">Amount</th>
<th class="px-4 py-3">Bank/Cash Ledger</th>
<th class="px-4 py-3">Action</th>
</tr>
</thead>
<tbody>
{% for row in bank_rows %}
<tr class="border-t border-slate-100 align-top">
<td class="px-4 py-3 whitespace-nowrap">{{ row.date or '-' }}</td>
<td class="px-4 py-3">
<div class="font-semibold">{{ row.party or row.narration or '-' }}</div>
{% if row.party and row.narration %}<div class="mt-1 max-w-xl text-xs text-slate-500">{{ row.narration }}</div>{% endif %}
{% if row.category %}<div class="mt-1 text-xs text-slate-500">Category: {{ row.category }}</div>{% endif %}
{% if row.reference %}<div class="text-xs text-slate-500">Ref: {{ row.reference }}</div>{% endif %}
</td>
<td class="px-4 py-3"><span class="rounded-full px-2 py-1 text-xs font-semibold {% if row.direction=='DEBIT' %}bg-amber-100 text-amber-800{% else %}bg-emerald-100 text-emerald-800{% endif %}">{{ row.direction }}</span></td>
<td class="px-4 py-3 text-right font-semibold">₹{{ '%.2f'|format(row.amount) }}</td>
<td class="px-4 py-3">
<form method="post" action="/tools/accounting/voucher-engine/automatic/bank/draft" class="flex min-w-[320px] gap-2">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="client_id" value="{{ selected_client.id }}">
<input type="hidden" name="tally_guid" value="{{ selected_tally_guid }}">
<input type="hidden" name="source_table" value="{{ row.source_table }}">
<input type="hidden" name="source_id" value="{{ row.source_id }}">
<select name="bank_ledger_name" required class="min-w-[190px] flex-1 rounded-lg border border-slate-300 bg-white px-2 py-2 text-xs">
<option value="">Select Bank/Cash ledger</option>
{% for ledger in bank_ledgers %}
<option value="{{ ledger.name }}">{{ ledger.name }}</option>
{% endfor %}
</select>
<button class="rounded-lg bg-slate-900 px-3 py-2 text-xs font-semibold text-white">Create Draft</button>
</form>
</td>
<td class="px-4 py-3 text-xs text-slate-500">{% if row.contra_hint %}Contra hint detected{% else %}Auto ledger matching from party/category{% endif %}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
{% endif %}
</section>
<section class="rounded-2xl bg-white shadow-soft">
<div class="flex flex-wrap items-center justify-between gap-3 border-b border-slate-200 p-5">
<div>
<h2 class="font-semibold">E-Way Bill Purchase / Sales Invoices</h2>
<p class="text-sm text-slate-500">Invoices are grouped by E-Way Bill + invoice + party. Every underlying item remains separate in the voucher draft.</p>
</div>
<form method="get" class="flex flex-wrap gap-2">
<input type="hidden" name="client_id" value="{{ selected_client.id }}">
<input type="hidden" name="tally_guid" value="{{ selected_tally_guid }}">
<input type="hidden" name="from_date" value="{{ from_date }}">
<input type="hidden" name="to_date" value="{{ to_date }}">
<select name="eway_source" class="rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm">
{% for source in sources.eway %}
<option value="{{ source.table_name }}" {% if selected_eway_source==source.table_name %}selected{% endif %}>{{ source.table_name }}</option>
{% endfor %}
</select>
<select name="direction" class="rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm">
<option value="" {% if not direction %}selected{% endif %}>Purchase + Sales</option>
<option value="PURCHASE" {% if direction=='PURCHASE' %}selected{% endif %}>Purchase / Inward</option>
<option value="SALES" {% if direction=='SALES' %}selected{% endif %}>Sales / Outward</option>
</select>
<button class="rounded-lg border border-slate-300 px-3 py-2 text-sm font-semibold">Apply</button>
</form>
</div>
{% if not sources.eway %}
<div class="p-8 text-center text-slate-500">
No existing E-Way Bill item table containing E-Way Bill number, item description and taxable value was discovered in the current ERP schema. Existing E-Way Bill features have not been modified.
</div>
{% elif not eway_invoices %}
<div class="p-8 text-center text-slate-500">No E-Way Bill item invoices were found for this client/period/filter.</div>
{% else %}
<div class="divide-y divide-slate-100">
{% for inv in eway_invoices %}
<article class="p-5">
<div class="flex flex-wrap items-start justify-between gap-4">
<div>
<div class="flex flex-wrap gap-2">
<span class="rounded-full px-2 py-1 text-xs font-semibold {% if inv.direction=='PURCHASE' %}bg-blue-100 text-blue-800{% elif inv.direction=='SALES' %}bg-violet-100 text-violet-800{% else %}bg-slate-100{% endif %}">{{ inv.direction }}</span>
<span class="rounded-full bg-slate-100 px-2 py-1 text-xs font-semibold">{{ inv.items|length }} stock item(s)</span>
</div>
<h3 class="mt-2 font-semibold">{{ inv.party_name or 'Party not available' }}</h3>
<p class="text-sm text-slate-500">GSTIN {{ inv.party_gstin or '-' }} · Invoice {{ inv.invoice_no or '-' }} · {{ inv.invoice_date or '-' }} · EWB {{ inv.eway_bill_no or '-' }}</p>
</div>
<div class="text-right">
<div class="font-semibold">Taxable ₹{{ '%.2f'|format(inv.taxable_value) }}</div>
<div class="text-xs text-slate-500">CGST {{ '%.2f'|format(inv.cgst) }} · SGST {{ '%.2f'|format(inv.sgst) }} · IGST {{ '%.2f'|format(inv.igst) }} · Cess {{ '%.2f'|format(inv.cess) }}</div>
</div>
</div>
<div class="mt-4 overflow-x-auto rounded-xl border border-slate-200">
<table class="min-w-full text-xs">
<thead><tr class="bg-slate-50 text-left uppercase text-slate-500"><th class="px-3 py-2">Stock Item / Description</th><th class="px-3 py-2">HSN</th><th class="px-3 py-2 text-right">Qty</th><th class="px-3 py-2">Unit</th><th class="px-3 py-2 text-right">Rate</th><th class="px-3 py-2 text-right">Taxable</th></tr></thead>
<tbody>
{% for item in inv.items %}
<tr class="border-t border-slate-100">
<td class="px-3 py-2 font-semibold">{{ item.item_name or '-' }}</td>
<td class="px-3 py-2">{{ item.hsn or '-' }}</td>
<td class="px-3 py-2 text-right">{{ item.quantity }}</td>
<td class="px-3 py-2">{{ item.unit or '-' }}</td>
<td class="px-3 py-2 text-right">{{ '%.4f'|format(item.rate) }}</td>
<td class="px-3 py-2 text-right">₹{{ '%.2f'|format(item.taxable_value) }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
<form method="post" action="/tools/accounting/voucher-engine/automatic/eway/draft" class="mt-4 flex justify-end">
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
<input type="hidden" name="client_id" value="{{ selected_client.id }}">
<input type="hidden" name="tally_guid" value="{{ selected_tally_guid }}">
<input type="hidden" name="source_table" value="{{ inv.source_table }}">
<input type="hidden" name="direction" value="{{ inv.direction }}">
<input type="hidden" name="eway_bill_no" value="{{ inv.eway_bill_no }}">
<input type="hidden" name="invoice_no" value="{{ inv.invoice_no }}">
<input type="hidden" name="invoice_date" value="{{ inv.invoice_date }}">
<input type="hidden" name="party_gstin" value="{{ inv.party_gstin }}">
<input type="hidden" name="party_name" value="{{ inv.party_name }}">
<button class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white">Create Stock-item {{ inv.direction|title }} Draft</button>
</form>
</article>
{% endfor %}
</div>
{% endif %}
</section>
<section class="rounded-2xl border border-slate-200 bg-slate-50 p-5">
<h2 class="font-semibold">Manual entry remains only as a fallback</h2>
<p class="mt-1 text-sm text-slate-600">Manual / adjustment voucher creation has not been removed. It remains useful for provisions, accruals, depreciation, reclassification, audit adjustments and source transactions that cannot yet be resolved automatically.</p>
<a href="/tools/accounting/voucher-engine?client_id={{ selected_client.id }}" class="mt-3 inline-flex rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm font-semibold">Open Manual / Review Voucher Engine</a>
</section>
{% endif %}
</div>
{% endblock %}