Validate FY mirrors and repair depreciation and TDS review

This commit is contained in:
A R R R Associates
2026-09-06 20:49:42 +05:30
parent 739973e370
commit eb83e5418d
12 changed files with 166 additions and 22 deletions
@@ -18,7 +18,7 @@
<section class="grid gap-4 md:grid-cols-3">
<div class="rounded-2xl bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase tracking-wide text-slate-500">ERP Local Agent</div><div class="mt-2 text-lg font-semibold {{ 'text-emerald-700' if agent_online else 'text-red-700' }}">{{ 'Connected' if agent_online else 'Offline' }}</div></div>
<div class="rounded-2xl bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase tracking-wide text-slate-500">SQLite Mirror</div><div class="mt-2 text-lg font-semibold {{ 'text-emerald-700' if mirror.ready else 'text-amber-700' }}">{{ 'Ready' if mirror.ready else 'Mirror required' }}</div><div class="mt-1 text-xs text-slate-500">{{ mirror.company.company_name if mirror.ready and mirror.company else '' }}</div></div>
<div class="rounded-2xl bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase tracking-wide text-slate-500">SQLite Mirror</div><div class="mt-2 text-lg font-semibold {{ 'text-emerald-700' if mirror.ready_for_financial_year else 'text-amber-700' }}">{{ 'Ready' if mirror.ready_for_financial_year else 'Mirror required' }}</div><div class="mt-1 text-xs text-slate-500">{{ mirror.company.company_name if mirror.ready_for_financial_year and mirror.company else '' }}</div></div>
<div class="rounded-2xl bg-white p-5 shadow-soft"><div class="text-xs font-semibold uppercase tracking-wide text-slate-500">Write-back</div><div class="mt-2 text-lg font-semibold text-slate-700">Controlled</div><div class="mt-1 text-xs text-slate-500">Tally is contacted only after approval/posting.</div></div>
</section>
@@ -122,8 +122,6 @@
{% endif %}
</section>
{% endif %}
<div class="rounded-xl border border-blue-200 bg-blue-50 px-4 py-3 text-sm text-blue-800">Phase 6 enables only controlled depreciation Journal write-back. All master and transaction synchronization remain read-only; no other Tally create/alter/delete operation is enabled.</div>
</div>
<script>
@@ -46,22 +46,28 @@
{% if selected_client %}
{% set prev = previous_mirror_status.mirror if previous_mirror_status and previous_mirror_status.mirror else {} %}
{% set curr = current_mirror_status.mirror if current_mirror_status and current_mirror_status.mirror else {} %}
{% set prev_ready = prev.ready_for_financial_year %}
{% set curr_ready = curr.ready_for_financial_year %}
<div class="mt-5 grid gap-3 md:grid-cols-2">
<div class="rounded-xl border p-4 {{ 'border-emerald-200 bg-emerald-50' if prev.ready else 'border-amber-200 bg-amber-50' }}">
<div class="rounded-xl border p-4 {{ 'border-emerald-200 bg-emerald-50' if prev_ready else 'border-amber-200 bg-amber-50' }}">
<div class="text-xs font-semibold uppercase text-slate-500">Previous FY Mirror · FY {{ previous_fy }}</div>
<div class="mt-1 font-semibold">{{ 'Ready' if prev.ready else 'Mirror required' }}</div>
{% if prev.ready %}
<div class="mt-1 font-semibold">{{ 'Ready' if prev_ready else 'Mirror required' }}</div>
{% if prev_ready %}
<div class="mt-1 text-xs text-slate-600">{{ prev.company.company_name }} · {{ prev.counts.voucher }} vouchers</div>
<div class="mt-1 break-all text-[11px] text-slate-500">{{ previous_mirror_status.mirror_db_path or prev.path or '' }}</div>
{% elif prev.ready and prev.financial_year_reason %}
<div class="mt-1 text-xs text-amber-800">{{ prev.financial_year_reason }}</div>
{% endif %}
</div>
<div class="rounded-xl border p-4 {{ 'border-emerald-200 bg-emerald-50' if curr.ready else 'border-amber-200 bg-amber-50' }}">
<div class="rounded-xl border p-4 {{ 'border-emerald-200 bg-emerald-50' if curr_ready else 'border-amber-200 bg-amber-50' }}">
<div class="text-xs font-semibold uppercase text-slate-500">Current FY Mirror · FY {{ current_fy }}</div>
<div class="mt-1 font-semibold">{{ 'Ready' if curr.ready else 'Mirror required' }}</div>
{% if curr.ready %}
<div class="mt-1 font-semibold">{{ 'Ready' if curr_ready else 'Mirror required' }}</div>
{% if curr_ready %}
<div class="mt-1 text-xs text-slate-600">{{ curr.company.company_name }} · {{ curr.counts.voucher }} vouchers</div>
<div class="mt-1 break-all text-[11px] text-slate-500">{{ current_mirror_status.mirror_db_path or curr.path or '' }}</div>
{% elif curr.ready and curr.financial_year_reason %}
<div class="mt-1 text-xs text-amber-800">{{ curr.financial_year_reason }}</div>
{% endif %}
</div>
</div>
@@ -70,7 +76,7 @@
<input type="hidden" name="client_id" value="{{ selected_client.id }}">
<input type="hidden" name="previous_fy" value="{{ previous_fy }}">
<input type="hidden" name="current_fy" value="{{ current_fy }}">
<button class="rounded-xl bg-slate-900 px-5 py-2 text-sm font-semibold text-white" {% if not node_online or not prev.ready or not curr.ready %}disabled{% endif %}>Compare Opening Balances</button>
<button class="rounded-xl bg-slate-900 px-5 py-2 text-sm font-semibold text-white" {% if not node_online or not prev_ready or not curr_ready %}disabled{% endif %}>Compare Opening Balances</button>
</form>
{% endif %}
</section>
@@ -1,5 +1,35 @@
{% 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-violet-600">TDS &amp; Withholding Tax</p><h1 class="mt-1 text-2xl font-semibold text-slate-900">TDS Compliance Review</h1><p class="mt-1 text-sm text-slate-500">Review expenses, purchases, journals and creditor postings from the client SQLite Accounting Mirror. Rules and thresholds come from the editable TDS Rule Master.</p></div><div class="flex gap-2"><a href="/tools/accounting/tds/rules" class="rounded-xl border px-3 py-2 text-sm font-semibold">Rule Master</a><a href="/tools/tally" class="rounded-xl border px-3 py-2 text-sm font-semibold">Tally</a></div></div>{% if error %}<div class="rounded-xl bg-red-50 p-3 text-sm text-red-800">{{ error }}</div>{% endif %}<form method="get" class="rounded-2xl bg-white p-5 shadow-soft"><div class="grid gap-3 lg:grid-cols-3"><label class="text-sm">Client<select name="client_id" required class="mt-1 w-full rounded-xl border px-3 py-2"><option value="">Select client</option>{% for c in clients %}<option value="{{ c.id }}" {% if selected_client and c.id==selected_client.id %}selected{% endif %}>{{ c.client_name }}</option>{% endfor %}</select></label><label class="text-sm">From<input type="date" name="date_from" value="{{ date_from }}" required class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">To<input type="date" name="date_to" value="{{ date_to }}" required class="mt-1 w-full rounded-xl border px-3 py-2"></label></div><input type="hidden" name="run" value="1"><button class="mt-4 rounded-xl bg-violet-700 px-4 py-2 text-sm font-semibold text-white">Run TDS Review</button></form>{% if review %}<div class="flex justify-end gap-2"><a href="/tools/tally/analysis/{{ review.analysis_run_id }}/download?client_id={{ selected_client.id }}&financial_year={{ date_from[:4] }}-{{ date_to[2:4] }}&format=xlsx" class="rounded-xl border border-emerald-300 bg-emerald-50 px-3 py-2 text-sm font-semibold text-emerald-800">Download Excel</a><a href="/tools/tally/analysis/{{ review.analysis_run_id }}/download?client_id={{ selected_client.id }}&financial_year={{ date_from[:4] }}-{{ date_to[2:4] }}&format=pdf" class="rounded-xl border px-3 py-2 text-sm font-semibold">Download PDF</a></div><div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-5">{% for k,v in review.summary.items() %}<div class="rounded-xl bg-white p-4 shadow-soft"><div class="text-xs uppercase text-slate-500">{{ k|replace('_',' ') }}</div><div class="mt-1 text-xl font-semibold">{{ v }}</div></div>{% endfor %}</div><div class="overflow-x-auto rounded-2xl bg-white shadow-soft"><table class="min-w-full text-sm"><thead class="bg-slate-50"><tr><th class="p-3 text-left">Date</th><th class="p-3 text-left">Party</th><th class="p-3 text-left">Ledger / Rule</th><th class="p-3 text-right">Base</th><th class="p-3 text-right">Expected</th><th class="p-3 text-right">Actual</th><th class="p-3 text-right">Liability</th><th class="p-3 text-left">Status</th></tr></thead><tbody>{% for x in review.transactions %}<tr class="border-t"><td class="p-3">{{ x.date }}</td><td class="p-3">{{ x.party }}</td><td class="p-3">{{ x.nature_ledger }}<div class="text-xs text-slate-500">{{ x.rule_name }} · {{ x.legacy_section }}</div></td><td class="p-3 text-right">{{ '%.2f'|format(x.taxable_base) }}</td><td class="p-3 text-right">{{ '%.2f'|format(x.expected_tds) }}</td><td class="p-3 text-right">{{ '%.2f'|format(x.actual_tds) }}</td><td class="p-3 text-right font-semibold">{{ '%.2f'|format(x.liability) }}</td><td class="p-3">{{ x.status }}</td></tr>{% endfor %}</tbody></table></div>{% endif %}{% if history %}<div class="rounded-2xl bg-white p-5 shadow-soft"><h2 class="font-semibold">TDS Analysis History</h2><div class="mt-3 overflow-x-auto"><table class="min-w-full text-sm"><tbody>{% for row in history %}<tr class="border-t"><td class="p-2">#{{ row.id }}</td><td class="p-2">{{ row.financial_year }}</td><td class="p-2">{{ row.period_from }} → {{ row.period_to }}</td><td class="p-2 text-right"><a class="font-semibold text-violet-700" href="/tools/tally/analysis/{{ row.id }}/download?client_id={{ selected_client.id }}&financial_year={{ row.financial_year }}&format=xlsx">Excel</a> · <a class="font-semibold text-violet-700" href="/tools/tally/analysis/{{ row.id }}/download?client_id={{ selected_client.id }}&financial_year={{ row.financial_year }}&format=pdf">PDF</a></td></tr>{% endfor %}</tbody></table></div></div>{% endif %}</div>
<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">TDS &amp; Withholding Tax</p><h1 class="mt-1 text-2xl font-semibold text-slate-900">TDS Compliance Review</h1><p class="mt-1 text-sm text-slate-500">Review expenses, purchases, journals and creditor postings from the client SQLite Accounting Mirror. Rules and thresholds come from the editable TDS Rule Master.</p></div><div class="flex gap-2"><a href="/tools/accounting/tds/rules" class="rounded-xl border px-3 py-2 text-sm font-semibold">Rule Master</a><a href="/tools/tally" class="rounded-xl border px-3 py-2 text-sm font-semibold">Tally</a></div></div>{% if error %}<div class="rounded-xl bg-red-50 p-3 text-sm text-red-800">{{ error }}</div>{% endif %}<form method="get" class="rounded-2xl bg-white p-5 shadow-soft"><div class="grid gap-3 lg:grid-cols-3"><label class="text-sm">Client<select name="client_id" required class="mt-1 w-full rounded-xl border px-3 py-2"><option value="">Select client</option>{% for c in clients %}<option value="{{ c.id }}" {% if selected_client and c.id==selected_client.id %}selected{% endif %}>{{ c.client_name }}</option>{% endfor %}</select></label><label class="text-sm">From<input type="date" name="date_from" value="{{ date_from }}" required class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">To<input type="date" name="date_to" value="{{ date_to }}" required class="mt-1 w-full rounded-xl border px-3 py-2"></label></div><input type="hidden" name="run" value="1"><button class="mt-4 rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white">Run TDS Review</button></form>{% if review %}<div class="flex justify-end gap-2"><a href="/tools/tally/analysis/{{ review.analysis_run_id }}/download?client_id={{ selected_client.id }}&financial_year={{ date_from[:4] }}-{{ date_to[2:4] }}&format=xlsx" class="rounded-xl border border-emerald-300 bg-emerald-50 px-3 py-2 text-sm font-semibold text-emerald-800">Download Excel</a><a href="/tools/tally/analysis/{{ review.analysis_run_id }}/download?client_id={{ selected_client.id }}&financial_year={{ date_from[:4] }}-{{ date_to[2:4] }}&format=pdf" class="rounded-xl border px-3 py-2 text-sm font-semibold">Download PDF</a></div><div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-5">{% for k,v in review.summary.items() %}<div class="rounded-xl bg-white p-4 shadow-soft"><div class="text-xs uppercase text-slate-500">{{ k|replace('_',' ') }}</div><div class="mt-1 text-xl font-semibold">{{ v }}</div></div>{% endfor %}</div><div class="overflow-x-auto rounded-2xl bg-white shadow-soft">
<div class="border-b border-slate-100 px-4 py-3"><h2 class="font-semibold text-slate-900">TDS Category Summary</h2><p class="mt-1 text-xs text-slate-500">Rule/category-wise totals for quick review before transaction-level exceptions.</p></div>
<table class="min-w-full text-sm">
<thead class="bg-slate-50">
<tr>
<th class="p-3 text-left">Category / Section</th>
<th class="p-3 text-right">Transactions</th>
<th class="p-3 text-right">Taxable Base</th>
<th class="p-3 text-right">Expected TDS</th>
<th class="p-3 text-right">Actual TDS</th>
<th class="p-3 text-right">Liability</th>
<th class="p-3 text-right">Not Deducted</th>
<th class="p-3 text-right">Short</th>
</tr>
</thead>
<tbody>
{% for row in review.category_summary %}
<tr class="border-t">
<td class="p-3"><div class="font-medium">{{ row.category }}</div><div class="text-xs text-slate-500">{{ row.legacy_section }}{% if row.statutory_reference %} · {{ row.statutory_reference }}{% endif %}</div></td>
<td class="p-3 text-right">{{ row.transactions }}</td>
<td class="p-3 text-right">{{ '%.2f'|format(row.taxable_base) }}</td>
<td class="p-3 text-right">{{ '%.2f'|format(row.expected_tds) }}</td>
<td class="p-3 text-right">{{ '%.2f'|format(row.actual_tds) }}</td>
<td class="p-3 text-right font-semibold">{{ '%.2f'|format(row.liability) }}</td>
<td class="p-3 text-right">{{ row.tds_not_deducted }}</td>
<td class="p-3 text-right">{{ row.short_deduction }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div><div class="overflow-x-auto rounded-2xl bg-white shadow-soft"><table class="min-w-full text-sm"><thead class="bg-slate-50"><tr><th class="p-3 text-left">Date</th><th class="p-3 text-left">Party</th><th class="p-3 text-left">Ledger / Rule</th><th class="p-3 text-right">Base</th><th class="p-3 text-right">Expected</th><th class="p-3 text-right">Actual</th><th class="p-3 text-right">Liability</th><th class="p-3 text-left">Status</th></tr></thead><tbody>{% for x in review.transactions %}<tr class="border-t"><td class="p-3">{{ x.date }}</td><td class="p-3">{{ x.party }}</td><td class="p-3">{{ x.nature_ledger }}<div class="text-xs text-slate-500">{{ x.rule_name }} · {{ x.legacy_section }}</div></td><td class="p-3 text-right">{{ '%.2f'|format(x.taxable_base) }}</td><td class="p-3 text-right">{{ '%.2f'|format(x.expected_tds) }}</td><td class="p-3 text-right">{{ '%.2f'|format(x.actual_tds) }}</td><td class="p-3 text-right font-semibold">{{ '%.2f'|format(x.liability) }}</td><td class="p-3">{{ x.status }}</td></tr>{% endfor %}</tbody></table></div>{% endif %}{% if history %}<div class="rounded-2xl bg-white p-5 shadow-soft"><h2 class="font-semibold">TDS Analysis History</h2><div class="mt-3 overflow-x-auto"><table class="min-w-full text-sm"><tbody>{% for row in history %}<tr class="border-t"><td class="p-2">#{{ row.id }}</td><td class="p-2">{{ row.financial_year }}</td><td class="p-2">{{ row.period_from }} → {{ row.period_to }}</td><td class="p-2 text-right"><a class="font-semibold text-brand-700" href="/tools/tally/analysis/{{ row.id }}/download?client_id={{ selected_client.id }}&financial_year={{ row.financial_year }}&format=xlsx">Excel</a> · <a class="font-semibold text-brand-700" href="/tools/tally/analysis/{{ row.id }}/download?client_id={{ selected_client.id }}&financial_year={{ row.financial_year }}&format=pdf">PDF</a></td></tr>{% endfor %}</tbody></table></div></div>{% endif %}</div>
{% endblock %}
File diff suppressed because one or more lines are too long
@@ -1,5 +1,5 @@
{% 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-violet-600">TDS &amp; Withholding Tax</p><h1 class="mt-1 text-2xl font-semibold text-slate-900">TDS Reconciliation</h1><p class="mt-1 text-sm text-slate-500">Compare live Tally TDS with return/form, challan and TRACES totals. Paste exports as one row per line: PAN, section/code, amount.</p></div><a href="/tools/tally" class="rounded-xl border px-3 py-2 text-sm font-semibold">Tally</a></div>{% if error %}<div class="rounded-xl bg-red-50 p-3 text-sm text-red-800">{{ error }}</div>{% endif %}<form method="post" class="rounded-2xl bg-white p-5 shadow-soft"><input type="hidden" name="csrf_token" value="{{ csrf_token }}"><div class="grid gap-3 lg:grid-cols-4"><label class="text-sm">Client<select name="client_id" required class="mt-1 w-full rounded-xl border px-3 py-2"><option value="">Select client</option>{% for c in clients %}<option value="{{ c.id }}" {% if selected_client and c.id==selected_client.id %}selected{% endif %}>{{ c.client_name }}</option>{% endfor %}</select></label><label class="text-sm">Tally GUID<input name="tally_guid" value="{{ tally_guid or '' }}" required class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">From<input type="date" name="date_from" value="{{ date_from or '' }}" required class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">To<input type="date" name="date_to" value="{{ date_to or '' }}" required class="mt-1 w-full rounded-xl border px-3 py-2"></label></div><div class="mt-4 grid gap-3 lg:grid-cols-3"><label class="text-sm">TDS return / form export<textarea name="return_data" rows="8" class="mt-1 w-full rounded-xl border p-2 font-mono text-xs">{{ return_data or '' }}</textarea></label><label class="text-sm">Challan export<textarea name="challan_data" rows="8" class="mt-1 w-full rounded-xl border p-2 font-mono text-xs">{{ challan_data or '' }}</textarea></label><label class="text-sm">TRACES export<textarea name="traces_data" rows="8" class="mt-1 w-full rounded-xl border p-2 font-mono text-xs">{{ traces_data or '' }}</textarea></label></div><button class="mt-4 rounded-xl bg-violet-700 px-4 py-2 text-sm font-semibold text-white">Run Reconciliation</button></form>{% if result %}<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-5">{% for label,value in [('Tally booked TDS',result.tally_actual),('Expected TDS',result.tally_expected),('Return / Forms',result.return_total),('Challans',result.challan_total),('TRACES',result.traces_total)] %}<div class="rounded-xl bg-white p-4 shadow-soft"><div class="text-xs uppercase text-slate-500">{{ label }}</div><div class="mt-1 text-xl font-semibold">₹{{ '%.2f'|format(value) }}</div></div>{% endfor %}</div><div class="grid gap-3 md:grid-cols-3"><div class="rounded-xl bg-white p-4 shadow-soft">Tally − Return: <b>₹{{ '%.2f'|format(result.tally_vs_return) }}</b></div><div class="rounded-xl bg-white p-4 shadow-soft">Return − Challan: <b>₹{{ '%.2f'|format(result.return_vs_challan) }}</b></div><div class="rounded-xl bg-white p-4 shadow-soft">Return − TRACES: <b>₹{{ '%.2f'|format(result.return_vs_traces) }}</b></div></div>{% endif %}</div>
<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">TDS &amp; Withholding Tax</p><h1 class="mt-1 text-2xl font-semibold text-slate-900">TDS Reconciliation</h1><p class="mt-1 text-sm text-slate-500">Compare live Tally TDS with return/form, challan and TRACES totals. Paste exports as one row per line: PAN, section/code, amount.</p></div><a href="/tools/tally" class="rounded-xl border px-3 py-2 text-sm font-semibold">Tally</a></div>{% if error %}<div class="rounded-xl bg-red-50 p-3 text-sm text-red-800">{{ error }}</div>{% endif %}<form method="post" class="rounded-2xl bg-white p-5 shadow-soft"><input type="hidden" name="csrf_token" value="{{ csrf_token }}"><div class="grid gap-3 lg:grid-cols-4"><label class="text-sm">Client<select name="client_id" required class="mt-1 w-full rounded-xl border px-3 py-2"><option value="">Select client</option>{% for c in clients %}<option value="{{ c.id }}" {% if selected_client and c.id==selected_client.id %}selected{% endif %}>{{ c.client_name }}</option>{% endfor %}</select></label><label class="text-sm">Tally GUID<input name="tally_guid" value="{{ tally_guid or '' }}" required class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">From<input type="date" name="date_from" value="{{ date_from or '' }}" required class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">To<input type="date" name="date_to" value="{{ date_to or '' }}" required class="mt-1 w-full rounded-xl border px-3 py-2"></label></div><div class="mt-4 grid gap-3 lg:grid-cols-3"><label class="text-sm">TDS return / form export<textarea name="return_data" rows="8" class="mt-1 w-full rounded-xl border p-2 font-mono text-xs">{{ return_data or '' }}</textarea></label><label class="text-sm">Challan export<textarea name="challan_data" rows="8" class="mt-1 w-full rounded-xl border p-2 font-mono text-xs">{{ challan_data or '' }}</textarea></label><label class="text-sm">TRACES export<textarea name="traces_data" rows="8" class="mt-1 w-full rounded-xl border p-2 font-mono text-xs">{{ traces_data or '' }}</textarea></label></div><button class="mt-4 rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white">Run Reconciliation</button></form>{% if result %}<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-5">{% for label,value in [('Tally booked TDS',result.tally_actual),('Expected TDS',result.tally_expected),('Return / Forms',result.return_total),('Challans',result.challan_total),('TRACES',result.traces_total)] %}<div class="rounded-xl bg-white p-4 shadow-soft"><div class="text-xs uppercase text-slate-500">{{ label }}</div><div class="mt-1 text-xl font-semibold">₹{{ '%.2f'|format(value) }}</div></div>{% endfor %}</div><div class="grid gap-3 md:grid-cols-3"><div class="rounded-xl bg-white p-4 shadow-soft">Tally − Return: <b>₹{{ '%.2f'|format(result.tally_vs_return) }}</b></div><div class="rounded-xl bg-white p-4 shadow-soft">Return − Challan: <b>₹{{ '%.2f'|format(result.return_vs_challan) }}</b></div><div class="rounded-xl bg-white p-4 shadow-soft">Return − TRACES: <b>₹{{ '%.2f'|format(result.return_vs_traces) }}</b></div></div>{% endif %}</div>
{% endblock %}
@@ -1,7 +1,7 @@
{% 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-violet-600">TDS &amp; Withholding Tax</p><h1 class="mt-1 text-2xl font-semibold text-slate-900">TDS Rule Master</h1><p class="mt-1 text-sm text-slate-500">Default rules are seeded for each firm and remain editable. Historical effective-date versions can be retained instead of hard-coding thresholds in Python.</p></div><a href="/tools/tally" class="rounded-xl border px-3 py-2 text-sm font-semibold">Back to Tally</a></div>
<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">TDS &amp; Withholding Tax</p><h1 class="mt-1 text-2xl font-semibold text-slate-900">TDS Rule Master</h1><p class="mt-1 text-sm text-slate-500">Default rules are seeded for each firm and remain editable. Historical effective-date versions can be retained instead of hard-coding thresholds in Python.</p></div><a href="/tools/tally" class="rounded-xl border px-3 py-2 text-sm font-semibold">Back to Tally</a></div>
{% if saved %}<div class="rounded-xl bg-emerald-50 p-3 text-sm text-emerald-800">Rule saved.</div>{% endif %}{% if error %}<div class="rounded-xl bg-red-50 p-3 text-sm text-red-800">{{ error }}</div>{% endif %}
<div class="space-y-4">{% for r in rules %}<form method="post" action="/tools/accounting/tds/rules/{{ r.id }}" class="rounded-2xl bg-white p-5 shadow-soft"><input type="hidden" name="csrf_token" value="{{ csrf_token }}"><div class="grid gap-3 lg:grid-cols-4"><label class="text-sm">Rule name<input name="name" value="{{ r.name }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">New Act reference<input name="statutory_reference" value="{{ r.statutory_reference }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">Legacy section<input name="legacy_section" value="{{ r.legacy_section or '' }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">Threshold mode<select name="threshold_mode" class="mt-1 w-full rounded-xl border px-3 py-2">{% for m in ['ANNUAL','SINGLE','BOTH','MONTHLY'] %}<option {% if r.threshold_mode==m %}selected{% endif %}>{{ m }}</option>{% endfor %}</select></label><label class="text-sm">Single / monthly threshold<input name="single_threshold" value="{{ r.single_threshold }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">Annual aggregate threshold<input name="aggregate_threshold" value="{{ r.aggregate_threshold }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">Rate - Individual/HUF %<input name="rate_individual_huf" value="{{ r.rate_individual_huf }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">Rate - Other %<input name="rate_other" value="{{ r.rate_other }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">No-PAN rate %<input name="no_pan_rate" value="{{ r.no_pan_rate }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm lg:col-span-3">Ledger/nature keywords<input name="nature_keywords" value="{{ r.nature_keywords }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label></div><div class="mt-3 flex flex-wrap gap-4 text-sm"><label><input type="checkbox" name="deduct_on_excess_only" {% if r.deduct_on_excess_only %}checked{% endif %}> Deduct only on amount exceeding threshold</label><label><input type="checkbox" name="applies_to_purchases" {% if r.applies_to_purchases %}checked{% endif %}> Purchases</label><label><input type="checkbox" name="applies_to_expenses" {% if r.applies_to_expenses %}checked{% endif %}> Expenses/services</label><label><input type="checkbox" name="is_active" {% if r.is_active %}checked{% endif %}> Active</label></div><button class="mt-4 rounded-xl bg-violet-700 px-4 py-2 text-sm font-semibold text-white">Save Rule</button></form>{% endfor %}</div></div>
<div class="space-y-4">{% for r in rules %}<form method="post" action="/tools/accounting/tds/rules/{{ r.id }}" class="rounded-2xl bg-white p-5 shadow-soft"><input type="hidden" name="csrf_token" value="{{ csrf_token }}"><div class="grid gap-3 lg:grid-cols-4"><label class="text-sm">Rule name<input name="name" value="{{ r.name }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">New Act reference<input name="statutory_reference" value="{{ r.statutory_reference }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">Legacy section<input name="legacy_section" value="{{ r.legacy_section or '' }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">Threshold mode<select name="threshold_mode" class="mt-1 w-full rounded-xl border px-3 py-2">{% for m in ['ANNUAL','SINGLE','BOTH','MONTHLY'] %}<option {% if r.threshold_mode==m %}selected{% endif %}>{{ m }}</option>{% endfor %}</select></label><label class="text-sm">Single / monthly threshold<input name="single_threshold" value="{{ r.single_threshold }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">Annual aggregate threshold<input name="aggregate_threshold" value="{{ r.aggregate_threshold }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">Rate - Individual/HUF %<input name="rate_individual_huf" value="{{ r.rate_individual_huf }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">Rate - Other %<input name="rate_other" value="{{ r.rate_other }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm">No-PAN rate %<input name="no_pan_rate" value="{{ r.no_pan_rate }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label><label class="text-sm lg:col-span-3">Ledger/nature keywords<input name="nature_keywords" value="{{ r.nature_keywords }}" class="mt-1 w-full rounded-xl border px-3 py-2"></label></div><div class="mt-3 flex flex-wrap gap-4 text-sm"><label><input type="checkbox" name="deduct_on_excess_only" {% if r.deduct_on_excess_only %}checked{% endif %}> Deduct only on amount exceeding threshold</label><label><input type="checkbox" name="applies_to_purchases" {% if r.applies_to_purchases %}checked{% endif %}> Purchases</label><label><input type="checkbox" name="applies_to_expenses" {% if r.applies_to_expenses %}checked{% endif %}> Expenses/services</label><label><input type="checkbox" name="is_active" {% if r.is_active %}checked{% endif %}> Active</label></div><button class="mt-4 rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white">Save Rule</button></form>{% endfor %}</div></div>
{% endblock %}