Add Phase 22 master integrity engine

This commit is contained in:
A R R R Associates
2026-08-26 22:12:29 +05:30
parent a01b95eab6
commit 31b576b363
5 changed files with 534 additions and 0 deletions
@@ -0,0 +1,120 @@
{% 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">Tools · Accounting · Phase 22</p>
<h1 class="mt-1 text-2xl font-semibold text-slate-900">Chart of Accounts / Master Integrity Engine</h1>
<p class="mt-1 max-w-4xl text-sm text-slate-500">Accounting + audit control over synced Tally Groups, Ledgers, Stock Groups, Stock Items and Units. This phase identifies master inconsistencies and routes corrections through the existing controlled tools; it does not silently alter Tally masters.</p>
</div>
<div class="flex flex-wrap gap-2">
<a href="/tools/accounting" class="rounded-xl border border-slate-300 bg-white px-3 py-2 text-sm font-semibold text-slate-700">Back to Accounting</a>
{% if selected_client %}
<a href="/tools/accounting/chart-of-accounts?client_id={{ selected_client.id }}{% if selected_tally_guid %}&tally_guid={{ selected_tally_guid }}{% endif %}" class="rounded-xl border border-blue-300 bg-blue-50 px-3 py-2 text-sm font-semibold text-blue-800">Open Chart of Accounts</a>
<a href="/tools/accounting/stock-items?client_id={{ selected_client.id }}{% if selected_tally_guid %}&tally_guid={{ selected_tally_guid }}{% endif %}" class="rounded-xl border border-indigo-300 bg-indigo-50 px-3 py-2 text-sm font-semibold text-indigo-800">Open Stock Intelligence</a>
{% endif %}
</div>
</div>
<form method="get" action="/tools/accounting/master-integrity" class="rounded-2xl border border-slate-200 bg-white p-4 shadow-soft">
<div class="grid gap-3 md:grid-cols-2 xl:grid-cols-6">
<select name="client_id" class="rounded-xl border border-slate-300 px-3 py-2 text-sm" onchange="this.form.submit()">
<option value="">Select client</option>
{% for client in clients %}<option value="{{ client.id }}" {% if selected_client and selected_client.id==client.id %}selected{% endif %}>{{ client.client_name }}</option>{% endfor %}
</select>
<select name="tally_guid" class="rounded-xl border border-slate-300 px-3 py-2 text-sm" onchange="this.form.submit()">
<option value="">Select synced Tally company</option>
{% for guid in available_guids %}<option value="{{ guid }}" {% if selected_tally_guid==guid %}selected{% endif %}>{{ guid }}</option>{% endfor %}
</select>
<input name="q" value="{{ q }}" placeholder="Search issue/master..." class="rounded-xl border border-slate-300 px-3 py-2 text-sm">
<select name="severity" class="rounded-xl border border-slate-300 px-3 py-2 text-sm">
<option value="">All severities</option>
{% for value in ['high','medium','low'] %}<option value="{{ value }}" {% if severity_filter==value %}selected{% endif %}>{{ value|title }}</option>{% endfor %}
</select>
<select name="master_type" class="rounded-xl border border-slate-300 px-3 py-2 text-sm">
<option value="">All master types</option>
{% for value in report.master_types %}<option value="{{ value }}" {% if master_type_filter==value %}selected{% endif %}>{{ value }}</option>{% endfor %}
</select>
<div class="flex gap-2">
<button class="flex-1 rounded-xl bg-slate-900 px-3 py-2 text-sm font-semibold text-white">Apply</button>
<a href="/tools/accounting/master-integrity{% if selected_client %}?client_id={{ selected_client.id }}{% endif %}" class="rounded-xl border border-slate-300 px-3 py-2 text-sm">Clear</a>
</div>
</div>
{% if report.issue_types %}
<div class="mt-3">
<select name="issue_type" class="w-full rounded-xl border border-slate-300 px-3 py-2 text-sm">
<option value="">All integrity checks</option>
{% for value in report.issue_types %}<option value="{{ value }}" {% if issue_type_filter==value %}selected{% endif %}>{{ value|replace('_',' ')|title }}</option>{% endfor %}
</select>
</div>
{% endif %}
</form>
{% if selected_client and selected_tally_guid %}
<div class="grid gap-3 sm:grid-cols-2 xl:grid-cols-5">
<div class="rounded-2xl bg-white p-4 shadow-soft"><div class="text-xs text-slate-500">Ledgers checked</div><div class="mt-1 text-2xl font-semibold">{{ report.summary.ledgers }}</div></div>
<div class="rounded-2xl bg-white p-4 shadow-soft"><div class="text-xs text-slate-500">Stock items checked</div><div class="mt-1 text-2xl font-semibold">{{ report.summary.stock_items }}</div></div>
<div class="rounded-2xl bg-white p-4 shadow-soft"><div class="text-xs text-slate-500">High priority</div><div class="mt-1 text-2xl font-semibold text-rose-700">{{ report.summary.high }}</div></div>
<div class="rounded-2xl bg-white p-4 shadow-soft"><div class="text-xs text-slate-500">Medium priority</div><div class="mt-1 text-2xl font-semibold text-amber-700">{{ report.summary.medium }}</div></div>
<div class="rounded-2xl bg-white p-4 shadow-soft"><div class="text-xs text-slate-500">Total exceptions</div><div class="mt-1 text-2xl font-semibold">{{ report.summary.issues }}</div></div>
</div>
<section class="overflow-hidden rounded-2xl bg-white shadow-soft">
<div class="flex flex-wrap items-center justify-between gap-2 border-b border-slate-200 p-4">
<div>
<h2 class="font-semibold text-slate-900">Exceptions requiring review</h2>
<p class="text-xs text-slate-500">Showing {{ filtered.total }} matching exception{{ '' if filtered.total==1 else 's' }}. Existing master tools remain the correction authority.</p>
</div>
<div class="text-xs text-slate-500">Groups {{ report.summary.groups }} · Stock Groups {{ report.summary.stock_groups }} · Units {{ report.summary.units }}</div>
</div>
<div class="overflow-x-auto">
<table class="min-w-full text-sm">
<thead class="bg-slate-50 text-left text-xs uppercase tracking-wide text-slate-500">
<tr><th class="px-4 py-3">Priority</th><th class="px-4 py-3">Master</th><th class="px-4 py-3">Issue</th><th class="px-4 py-3">Current</th><th class="px-4 py-3">Suggested review</th><th class="px-4 py-3">Reason</th><th class="px-4 py-3">Action</th></tr>
</thead>
<tbody>
{% for row in filtered.rows %}
<tr class="border-t border-slate-100 align-top">
<td class="px-4 py-3"><span class="rounded-full px-2 py-1 text-xs font-semibold {% if row.severity=='high' %}bg-rose-100 text-rose-800{% elif row.severity=='medium' %}bg-amber-100 text-amber-800{% else %}bg-slate-100 text-slate-700{% endif %}">{{ row.severity|title }}</span></td>
<td class="px-4 py-3"><div class="font-semibold text-slate-900">{{ row.name }}</div><div class="text-xs text-slate-500">{{ row.master_type }}{% if row.related %} · Related: {{ row.related }}{% endif %}</div></td>
<td class="px-4 py-3 text-xs font-semibold text-slate-700">{{ row.kind|replace('_',' ')|title }}</td>
<td class="px-4 py-3 text-slate-600">{{ row.current or '—' }}</td>
<td class="px-4 py-3 text-slate-700">{{ row.suggested or 'Review' }}</td>
<td class="max-w-md px-4 py-3 text-slate-600">{{ row.reason }}</td>
<td class="px-4 py-3">
{% if row.master_type == 'Ledger' %}
<a href="/tools/accounting/chart-of-accounts?client_id={{ selected_client.id }}&tally_guid={{ selected_tally_guid }}&q={{ row.name|urlencode }}" class="whitespace-nowrap rounded-lg border border-blue-300 bg-blue-50 px-2.5 py-1.5 text-xs font-semibold text-blue-800">Review Ledger</a>
{% elif row.master_type == 'Stock Item' or row.master_type == 'Unit' %}
<a href="/tools/accounting/stock-items?client_id={{ selected_client.id }}&tally_guid={{ selected_tally_guid }}&q={{ row.name|urlencode }}" class="whitespace-nowrap rounded-lg border border-indigo-300 bg-indigo-50 px-2.5 py-1.5 text-xs font-semibold text-indigo-800">Review Stock</a>
{% else %}
<a href="/tools/accounting/chart-of-accounts?client_id={{ selected_client.id }}&tally_guid={{ selected_tally_guid }}&view=groups" class="whitespace-nowrap rounded-lg border border-slate-300 px-2.5 py-1.5 text-xs font-semibold text-slate-700">Review Group</a>
{% endif %}
</td>
</tr>
{% else %}
<tr><td colspan="7" class="px-4 py-8 text-center text-slate-500">No integrity exceptions match the selected filters.</td></tr>
{% endfor %}
</tbody>
</table>
</div>
{% if filtered.pages > 1 %}
<div class="flex items-center justify-between border-t border-slate-200 p-4 text-sm">
<div>Page {{ filtered.page }} of {{ filtered.pages }}</div>
<div class="flex gap-2">
{% if filtered.page > 1 %}<a class="rounded-lg border px-3 py-1.5" href="?client_id={{ selected_client.id }}&tally_guid={{ selected_tally_guid }}&q={{ q|urlencode }}&severity={{ severity_filter }}&master_type={{ master_type_filter|urlencode }}&issue_type={{ issue_type_filter }}&page={{ filtered.page-1 }}&per_page={{ filtered.per_page }}">Previous</a>{% endif %}
{% if filtered.page < filtered.pages %}<a class="rounded-lg border px-3 py-1.5" href="?client_id={{ selected_client.id }}&tally_guid={{ selected_tally_guid }}&q={{ q|urlencode }}&severity={{ severity_filter }}&master_type={{ master_type_filter|urlencode }}&issue_type={{ issue_type_filter }}&page={{ filtered.page+1 }}&per_page={{ filtered.per_page }}">Next</a>{% endif %}
</div>
</div>
{% endif %}
</section>
<div class="rounded-2xl border border-blue-200 bg-blue-50 p-4 text-sm text-blue-900">
<div class="font-semibold">Dual-use control</div>
<p class="mt-1">For accounting, this identifies masters that can cause wrong voucher classification or posting. For audit, the same report becomes a master-data exception review. Phase 22 deliberately does not auto-delete, rename or regroup Tally masters.</p>
</div>
{% elif selected_client %}
<div class="rounded-2xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900">No synced Tally company is available for this client. Run the existing Chart of Accounts / Stock Item sync first.</div>
{% endif %}
</div>
{% endblock %}
@@ -20,6 +20,7 @@
</div>
<div class="flex flex-wrap gap-2">
<a href="/tools/accounting/chart-of-accounts{% if selected_client %}?client_id={{ selected_client.id }}{% endif %}" class="rounded-xl bg-blue-700 px-3 py-2 text-sm font-semibold text-white">Chart of Accounts - Groups & Ledgers</a>
<a href="/tools/accounting/master-integrity{% if selected_client %}?client_id={{ selected_client.id }}{% endif %}" class="rounded-xl border border-rose-300 bg-white px-3 py-2 text-sm font-semibold text-rose-800">Master Integrity Engine</a>
<a href="/tools/accounting/stock-items{% if selected_client %}?client_id={{ selected_client.id }}{% endif %}" class="rounded-xl border border-indigo-300 bg-white px-3 py-2 text-sm font-semibold text-indigo-800">Stock Item Intelligence</a>
<a href="/tools/accounting/opening-balances{% if selected_client %}?client_id={{ selected_client.id }}{% endif %}" class="rounded-xl border border-amber-300 bg-white px-3 py-2 text-sm font-semibold text-amber-800">Opening Balance Review</a>
<a href="/tools/accounting/voucher-engine{% if selected_client %}?client_id={{ selected_client.id }}{% endif %}" class="rounded-xl border border-blue-300 bg-white px-3 py-2 text-sm font-semibold text-blue-800">Accounting Voucher Engine</a>