Refine opening balance review with summary and exception workflow
This commit is contained in:
@@ -3,10 +3,10 @@
|
||||
<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 · Phase 21A</p>
|
||||
<p class="text-xs font-semibold uppercase tracking-[0.16em] text-brand-600">Accounting · Phase 21A v2</p>
|
||||
<h1 class="mt-1 text-2xl font-semibold text-slate-900">Opening Balance Review & Correction</h1>
|
||||
<p class="mt-1 max-w-5xl text-sm text-slate-500">
|
||||
Compare previous-year Tally closing balances with current-year opening balances for Ledgers and Stock Items. Safe selected differences can be applied directly to current-year Tally masters and are re-read for verification.
|
||||
Summary-first review of previous-year closing balances against current-year openings. Matched and new zero-balance masters stay out of the main review; actionable differences are shown immediately and retain the existing controlled Tally correction workflow.
|
||||
</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
@@ -50,7 +50,6 @@
|
||||
</label>
|
||||
<div class="flex items-end"><button class="rounded-xl bg-slate-900 px-5 py-2 text-sm font-semibold text-white" {% if not node_online %}disabled{% endif %}>Compare Opening Balances</button></div>
|
||||
</form>
|
||||
<p class="mt-2 text-xs text-slate-500">Phase 21A v1 intentionally requires separate previous-year and current-year Tally companies. This avoids treating a current company's latest closing balance as the prior-year audited closing.</p>
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
@@ -68,7 +67,7 @@
|
||||
<td class="px-4 py-3">{{ run.current_company_name }}</td>
|
||||
<td class="px-4 py-3">{{ run.ledger_count }}</td>
|
||||
<td class="px-4 py-3">{{ run.stock_item_count }}</td>
|
||||
<td class="px-4 py-3 text-right"><a class="font-semibold text-brand-700 hover:underline" href="?client_id={{ selected_client.id }}&run_id={{ run.id }}">Open</a></td>
|
||||
<td class="px-4 py-3 text-right"><a class="font-semibold text-brand-700 hover:underline" href="?client_id={{ selected_client.id }}&run_id={{ run.id }}&tab=summary">Open Summary</a></td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
@@ -78,29 +77,177 @@
|
||||
{% endif %}
|
||||
|
||||
{% if selected_run %}
|
||||
<div class="rounded-2xl border border-amber-200 bg-amber-50 p-4 text-sm text-amber-900">
|
||||
<strong>Direct Tally correction control:</strong> only matched current-year masters with a genuine opening difference are eligible. Missing/new masters, ambiguous matches and stock unit differences are never changed automatically. Every applied row is re-read from Tally and marked Verified or Failed.
|
||||
</div>
|
||||
<section class="rounded-2xl bg-white p-5 shadow-soft">
|
||||
<div class="flex flex-wrap items-start justify-between gap-3">
|
||||
<div>
|
||||
<p class="text-xs font-semibold uppercase tracking-[0.14em] text-slate-500">Run #{{ selected_run.id }}</p>
|
||||
<h2 class="mt-1 text-lg font-semibold">{{ selected_run.previous_company_name }} closing → {{ selected_run.current_company_name }} opening</h2>
|
||||
</div>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=summary" class="rounded-xl {% if tab=='summary' %}bg-brand-600 text-white{% else %}border border-slate-300 bg-white{% endif %} px-4 py-2 text-sm font-semibold">Summary</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<nav class="flex gap-2">
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=ledgers" class="rounded-xl px-4 py-2 text-sm font-semibold {% if tab=='ledgers' %}bg-brand-600 text-white{% else %}border border-slate-300 bg-white{% endif %}">Ledger Openings</a>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock" class="rounded-xl px-4 py-2 text-sm font-semibold {% if tab=='stock' %}bg-brand-600 text-white{% else %}border border-slate-300 bg-white{% endif %}">Stock Openings</a>
|
||||
</nav>
|
||||
{% if tab=='summary' %}
|
||||
<section class="space-y-4">
|
||||
<div>
|
||||
<h2 class="text-lg font-semibold text-slate-900">Ledger Opening Summary</h2>
|
||||
<p class="text-sm text-slate-500">Matched records are summarized only. Click a category when you need its detailed report.</p>
|
||||
</div>
|
||||
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=ledgers&status=matched" class="rounded-2xl border border-emerald-200 bg-emerald-50 p-4">
|
||||
<div class="text-xs font-semibold uppercase text-emerald-700">Matched</div><div class="mt-1 text-3xl font-bold text-emerald-900">{{ summary.ledgers.matched }}</div><div class="mt-2 text-xs text-emerald-700">View detailed report</div>
|
||||
</a>
|
||||
<a href="#ledger-actions" class="rounded-2xl border border-amber-300 bg-amber-50 p-4">
|
||||
<div class="text-xs font-semibold uppercase text-amber-700">Differences</div><div class="mt-1 text-3xl font-bold text-amber-900">{{ summary.ledgers.difference }}</div><div class="mt-2 text-xs text-amber-700">Review & apply below</div>
|
||||
</a>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=ledgers&status=missing_in_current_year" class="rounded-2xl border border-red-200 bg-red-50 p-4">
|
||||
<div class="text-xs font-semibold uppercase text-red-700">Missing in Current Year</div><div class="mt-1 text-3xl font-bold text-red-900">{{ summary.ledgers.missing_in_current_year }}</div><div class="mt-2 text-xs text-red-700">Review details</div>
|
||||
</a>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=ledgers&status=new_in_current_year" class="rounded-2xl border border-slate-200 bg-slate-50 p-4">
|
||||
<div class="text-xs font-semibold uppercase text-slate-600">New in Current Year</div><div class="mt-1 text-3xl font-bold text-slate-900">{{ summary.ledgers.new_in_current_year }}</div><div class="mt-2 text-xs text-slate-600">Zero-balance rows hidden by default</div>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
<form method="post" action="/tools/accounting/opening-balances/apply" class="space-y-4">
|
||||
<div class="pt-3">
|
||||
<h2 class="text-lg font-semibold text-slate-900">Stock Opening Summary</h2>
|
||||
<p class="text-sm text-slate-500">Quantity, value and unit exceptions are separated so the reviewer sees only the issue that needs attention.</p>
|
||||
</div>
|
||||
<div class="grid gap-3 sm:grid-cols-2 lg:grid-cols-4">
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status=matched" class="rounded-2xl border border-emerald-200 bg-emerald-50 p-4">
|
||||
<div class="text-xs font-semibold uppercase text-emerald-700">Matched</div><div class="mt-1 text-3xl font-bold text-emerald-900">{{ summary.stock_items.matched }}</div><div class="mt-2 text-xs text-emerald-700">View detailed report</div>
|
||||
</a>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status=quantity_difference" class="rounded-2xl border border-amber-200 bg-amber-50 p-4">
|
||||
<div class="text-xs font-semibold uppercase text-amber-700">Quantity Difference</div><div class="mt-1 text-3xl font-bold text-amber-900">{{ summary.stock_items.quantity_difference }}</div><div class="mt-2 text-xs text-amber-700">Review details</div>
|
||||
</a>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status=value_difference" class="rounded-2xl border border-amber-200 bg-amber-50 p-4">
|
||||
<div class="text-xs font-semibold uppercase text-amber-700">Value Difference</div><div class="mt-1 text-3xl font-bold text-amber-900">{{ summary.stock_items.value_difference }}</div><div class="mt-2 text-xs text-amber-700">Review details</div>
|
||||
</a>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status=quantity_and_value_difference" class="rounded-2xl border border-orange-300 bg-orange-50 p-4">
|
||||
<div class="text-xs font-semibold uppercase text-orange-700">Qty + Value Difference</div><div class="mt-1 text-3xl font-bold text-orange-900">{{ summary.stock_items.quantity_and_value_difference }}</div><div class="mt-2 text-xs text-orange-700">Review & apply</div>
|
||||
</a>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status=unit_difference" class="rounded-2xl border border-red-200 bg-red-50 p-4">
|
||||
<div class="text-xs font-semibold uppercase text-red-700">Unit Difference</div><div class="mt-1 text-3xl font-bold text-red-900">{{ summary.stock_items.unit_difference }}</div><div class="mt-2 text-xs text-red-700">Blocked from automatic correction</div>
|
||||
</a>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status=missing_in_current_year" class="rounded-2xl border border-red-200 bg-red-50 p-4">
|
||||
<div class="text-xs font-semibold uppercase text-red-700">Missing in Current Year</div><div class="mt-1 text-3xl font-bold text-red-900">{{ summary.stock_items.missing_in_current_year }}</div><div class="mt-2 text-xs text-red-700">Review details</div>
|
||||
</a>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status=new_in_current_year" class="rounded-2xl border border-slate-200 bg-slate-50 p-4">
|
||||
<div class="text-xs font-semibold uppercase text-slate-600">New in Current Year</div><div class="mt-1 text-3xl font-bold text-slate-900">{{ summary.stock_items.new_in_current_year }}</div><div class="mt-2 text-xs text-slate-600">Zero-balance rows hidden by default</div>
|
||||
</a>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<form method="post" action="/tools/accounting/opening-balances/apply" class="space-y-5">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<input type="hidden" name="client_id" value="{{ selected_client.id }}">
|
||||
<input type="hidden" name="run_id" value="{{ selected_run.id }}">
|
||||
|
||||
{% if tab=='ledgers' %}
|
||||
<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">Ledger Opening Comparison</h2><p class="text-sm text-slate-500">{{ selected_run.previous_company_name }} closing → {{ selected_run.current_company_name }} opening</p></div>
|
||||
<select onchange="location.href='?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=ledgers&status='+encodeURIComponent(this.value)" class="rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm">
|
||||
<option value="">All statuses</option>
|
||||
{% for value,label in [('matched','Matched'),('difference','Difference'),('missing_in_current_year','Missing in Current Year'),('new_in_current_year','New in Current Year')] %}<option value="{{ value }}" {% if status_filter==value %}selected{% endif %}>{{ label }}</option>{% endfor %}
|
||||
</select>
|
||||
<section id="ledger-actions" class="rounded-2xl bg-white shadow-soft">
|
||||
<div class="flex flex-wrap items-start justify-between gap-3 border-b border-slate-200 p-5">
|
||||
<div>
|
||||
<h2 class="font-semibold">Ledger Differences — Action Required</h2>
|
||||
<p class="text-sm text-slate-500">Only ledgers with an actual previous-closing/current-opening difference are shown here.</p>
|
||||
</div>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=ledgers&status=difference" class="text-sm font-semibold text-brand-700 hover:underline">Open detailed report</a>
|
||||
</div>
|
||||
<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-3 py-2">Apply</th><th class="px-3 py-2">Previous Ledger</th><th class="px-3 py-2 text-right">PY Closing</th><th class="px-3 py-2">Current Ledger</th><th class="px-3 py-2 text-right">CY Opening</th><th class="px-3 py-2 text-right">Difference</th><th class="px-3 py-2">Match</th><th class="px-3 py-2">Correction</th></tr></thead>
|
||||
<tbody>
|
||||
{% for item in ledger_action_rows %}
|
||||
<tr class="border-t border-slate-100">
|
||||
<td class="px-3 py-3"><input type="checkbox" name="ledger_ids" value="{{ item.id }}"></td>
|
||||
<td class="px-3 py-3"><div class="font-semibold">{{ item.previous_name }}</div><div class="text-xs text-slate-500">{{ item.previous_group }}</div></td>
|
||||
<td class="px-3 py-3 text-right">{{ '%.2f'|format(item.previous_closing_balance) }}</td>
|
||||
<td class="px-3 py-3"><div class="font-semibold">{{ item.current_name }}</div><div class="text-xs text-slate-500">{{ item.current_group }}</div></td>
|
||||
<td class="px-3 py-3 text-right">{{ '%.2f'|format(item.current_opening_balance) }}</td>
|
||||
<td class="px-3 py-3 text-right font-semibold">{{ '%.2f'|format(0 if item.difference|abs < 0.005 else item.difference) }}</td>
|
||||
<td class="px-3 py-3">{{ item.match_method|replace('_',' ')|title }} · {{ item.confidence }}%</td>
|
||||
<td class="px-3 py-3">{{ item.correction_status|replace('_',' ')|title }}{% if item.correction_note %}<div class="max-w-xs text-xs text-slate-500">{{ item.correction_note }}</div>{% endif %}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="8" class="p-8 text-center text-emerald-700">No Ledger opening differences require action.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
{% if summary.ledgers.difference > ledger_action_rows|length %}<div class="border-t border-slate-200 p-3 text-xs text-slate-500">Showing the first {{ ledger_action_rows|length }} differences here. Open the detailed report to review the remaining rows.</div>{% endif %}
|
||||
</section>
|
||||
|
||||
<section class="rounded-2xl bg-white shadow-soft">
|
||||
<div class="flex flex-wrap items-start justify-between gap-3 border-b border-slate-200 p-5">
|
||||
<div>
|
||||
<h2 class="font-semibold">Stock Opening Differences — Action Required</h2>
|
||||
<p class="text-sm text-slate-500">Quantity/value differences can be selected for correction. Unit differences are shown but remain blocked.</p>
|
||||
</div>
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status=quantity_and_value_difference" class="text-sm font-semibold text-brand-700 hover:underline">Open stock details</a>
|
||||
</div>
|
||||
<div class="overflow-x-auto">
|
||||
<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">Apply</th><th class="px-3 py-2">Previous Stock Item</th><th class="px-3 py-2">PY Closing</th><th class="px-3 py-2">Current Stock Item</th><th class="px-3 py-2">CY Opening</th><th class="px-3 py-2">Difference</th><th class="px-3 py-2">Status</th><th class="px-3 py-2">Correction</th></tr></thead>
|
||||
<tbody>
|
||||
{% for item in stock_action_rows %}
|
||||
<tr class="border-t border-slate-100 align-top">
|
||||
<td class="px-3 py-3">{% if item.match_status != 'unit_difference' and item.previous_unit|lower == item.current_unit|lower %}<input type="checkbox" name="stock_ids" value="{{ item.id }}">{% else %}<span class="text-red-600">Blocked</span>{% endif %}</td>
|
||||
<td class="px-3 py-3"><div class="font-semibold">{{ item.previous_name }}</div><div class="text-slate-500">{{ item.previous_group }} · HSN {{ item.previous_hsn or '-' }}</div></td>
|
||||
<td class="px-3 py-3"><div>{{ item.previous_closing_qty }} {{ item.previous_unit }}</div><div>₹{{ '%.2f'|format(item.previous_closing_value) }}</div></td>
|
||||
<td class="px-3 py-3"><div class="font-semibold">{{ item.current_name }}</div><div class="text-slate-500">{{ item.current_group }} · HSN {{ item.current_hsn or '-' }}</div></td>
|
||||
<td class="px-3 py-3"><div>{{ item.current_opening_qty }} {{ item.current_unit }}</div><div>₹{{ '%.2f'|format(item.current_opening_value) }}</div></td>
|
||||
<td class="px-3 py-3"><div>Qty {{ 0 if item.quantity_difference|abs < 0.000001 else item.quantity_difference }}</div><div>Value ₹{{ '%.2f'|format(0 if item.value_difference|abs < 0.005 else item.value_difference) }}</div></td>
|
||||
<td class="px-3 py-3">{{ item.match_status|replace('_',' ')|title }}<div class="text-slate-500">{{ item.match_method|replace('_',' ')|title }} · {{ item.confidence }}%</div></td>
|
||||
<td class="px-3 py-3">{{ item.correction_status|replace('_',' ')|title }}{% if item.correction_note %}<div class="max-w-xs text-slate-500">{{ item.correction_note }}</div>{% endif %}</td>
|
||||
</tr>
|
||||
{% else %}
|
||||
<tr><td colspan="8" class="p-8 text-center text-emerald-700">No Stock Item opening differences require action.</td></tr>
|
||||
{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% if ledger_action_rows or stock_action_rows %}
|
||||
<section class="rounded-2xl border border-red-200 bg-red-50 p-5">
|
||||
<h3 class="font-semibold text-red-900">Apply selected safe corrections directly to current-year Tally</h3>
|
||||
<p class="mt-1 text-sm text-red-800">Existing safeguards are unchanged: current openings are rechecked immediately before write and every altered master is re-read from Tally afterward.</p>
|
||||
<div class="mt-3 flex flex-wrap gap-3">
|
||||
<input name="confirm_text" required placeholder="APPLY OPENING BALANCES" class="min-w-[280px] rounded-lg border border-red-300 bg-white px-3 py-2 text-sm">
|
||||
<button class="rounded-lg bg-red-700 px-4 py-2 text-sm font-semibold text-white">Apply Selected Changes</button>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
{% elif tab=='ledgers' %}
|
||||
<section class="rounded-2xl bg-white shadow-soft">
|
||||
<div class="flex flex-wrap items-start justify-between gap-3 border-b border-slate-200 p-5">
|
||||
<div>
|
||||
<h2 class="font-semibold">Ledger Detailed Report</h2>
|
||||
<p class="text-sm text-slate-500">{{ status_filter|replace('_',' ')|title }} · {{ detail_total }} row(s). This detailed list is opened only on demand.</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{% for value,label in [('matched','Matched'),('difference','Differences'),('missing_in_current_year','Missing'),('new_in_current_year','New')] %}
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=ledgers&status={{ value }}" class="rounded-lg {% if status_filter==value %}bg-brand-600 text-white{% else %}border border-slate-300 bg-white{% endif %} px-3 py-2 text-xs font-semibold">{{ label }}</a>
|
||||
{% endfor %}
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=summary" class="rounded-lg border border-slate-300 bg-white px-3 py-2 text-xs font-semibold">Back to Summary</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if status_filter=='new_in_current_year' %}
|
||||
<div class="border-b border-slate-200 px-5 py-3 text-xs text-slate-600">
|
||||
{% if show_zero_new %}
|
||||
Zero-balance new Ledgers are currently visible.
|
||||
<a class="font-semibold text-brand-700" href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=ledgers&status=new_in_current_year">Hide zero-balance new Ledgers</a>
|
||||
{% else %}
|
||||
Zero-balance new Ledgers are hidden by default.
|
||||
<a class="font-semibold text-brand-700" href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=ledgers&status=new_in_current_year&show_zero_new=1">Show them</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/tools/accounting/opening-balances/apply">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<input type="hidden" name="client_id" value="{{ selected_client.id }}">
|
||||
<input type="hidden" name="run_id" value="{{ selected_run.id }}">
|
||||
<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-3 py-2">Apply</th><th class="px-3 py-2">Previous Ledger</th><th class="px-3 py-2 text-right">PY Closing</th><th class="px-3 py-2">Current Ledger</th><th class="px-3 py-2 text-right">CY Opening</th><th class="px-3 py-2 text-right">Difference</th><th class="px-3 py-2">Status</th><th class="px-3 py-2">Correction</th></tr></thead>
|
||||
@@ -112,25 +259,66 @@
|
||||
<td class="px-3 py-3 text-right">{{ '%.2f'|format(item.previous_closing_balance) }}</td>
|
||||
<td class="px-3 py-3"><div class="font-semibold">{{ item.current_name or '—' }}</div><div class="text-xs text-slate-500">{{ item.current_group }}</div></td>
|
||||
<td class="px-3 py-3 text-right">{{ '%.2f'|format(item.current_opening_balance) }}</td>
|
||||
<td class="px-3 py-3 text-right font-semibold">{{ '%.2f'|format(item.difference) }}</td>
|
||||
<td class="px-3 py-3 text-right font-semibold">{{ '%.2f'|format(0 if item.difference|abs < 0.005 else item.difference) }}</td>
|
||||
<td class="px-3 py-3">{{ item.match_status|replace('_',' ')|title }}{% if item.match_method %}<div class="text-xs text-slate-500">{{ item.match_method|replace('_',' ')|title }} · {{ item.confidence }}%</div>{% endif %}</td>
|
||||
<td class="px-3 py-3">{{ item.correction_status|replace('_',' ')|title }}{% if item.correction_note %}<div class="max-w-xs text-xs text-slate-500">{{ item.correction_note }}</div>{% endif %}</td>
|
||||
</tr>
|
||||
{% else %}<tr><td colspan="8" class="p-8 text-center text-slate-500">No ledger rows for this filter.</td></tr>{% endfor %}
|
||||
{% else %}<tr><td colspan="8" class="p-8 text-center text-slate-500">No Ledger rows for this category.</td></tr>{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
{% else %}
|
||||
<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">Stock Item Opening Comparison</h2><p class="text-sm text-slate-500">Quantity, unit and value are checked separately.</p></div>
|
||||
<select onchange="location.href='?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status='+encodeURIComponent(this.value)" class="rounded-lg border border-slate-300 bg-white px-3 py-2 text-sm">
|
||||
<option value="">All statuses</option>
|
||||
{% for value,label in [('matched','Matched'),('quantity_difference','Quantity Difference'),('value_difference','Value Difference'),('quantity_and_value_difference','Quantity + Value Difference'),('unit_difference','Unit Difference'),('missing_in_current_year','Missing in Current Year'),('new_in_current_year','New in Current Year')] %}<option value="{{ value }}" {% if status_filter==value %}selected{% endif %}>{{ label }}</option>{% endfor %}
|
||||
</select>
|
||||
{% if status_filter=='difference' and ledgers %}
|
||||
<div class="border-t border-slate-200 p-4">
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<input name="confirm_text" required placeholder="APPLY OPENING BALANCES" class="min-w-[280px] rounded-lg border border-red-300 px-3 py-2 text-sm">
|
||||
<button class="rounded-lg bg-red-700 px-4 py-2 text-sm font-semibold text-white">Apply Selected Changes</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
{% if pages > 1 %}
|
||||
<div class="flex items-center justify-between border-t border-slate-200 p-4 text-sm">
|
||||
<span>Page {{ page }} of {{ pages }}</span>
|
||||
<div class="flex gap-2">
|
||||
{% if page>1 %}<a class="rounded-lg border border-slate-300 px-3 py-2" href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=ledgers&status={{ status_filter }}&page={{ page-1 }}{% if show_zero_new %}&show_zero_new=1{% endif %}">Previous</a>{% endif %}
|
||||
{% if page<pages %}<a class="rounded-lg border border-slate-300 px-3 py-2" href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=ledgers&status={{ status_filter }}&page={{ page+1 }}{% if show_zero_new %}&show_zero_new=1{% endif %}">Next</a>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
|
||||
{% elif tab=='stock' %}
|
||||
<section class="rounded-2xl bg-white shadow-soft">
|
||||
<div class="flex flex-wrap items-start justify-between gap-3 border-b border-slate-200 p-5">
|
||||
<div>
|
||||
<h2 class="font-semibold">Stock Item Detailed Report</h2>
|
||||
<p class="text-sm text-slate-500">{{ status_filter|replace('_',' ')|title }} · {{ detail_total }} row(s).</p>
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2">
|
||||
{% for value,label in [('matched','Matched'),('quantity_difference','Qty Difference'),('value_difference','Value Difference'),('quantity_and_value_difference','Qty + Value'),('unit_difference','Unit Difference'),('missing_in_current_year','Missing'),('new_in_current_year','New')] %}
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status={{ value }}" class="rounded-lg {% if status_filter==value %}bg-brand-600 text-white{% else %}border border-slate-300 bg-white{% endif %} px-3 py-2 text-xs font-semibold">{{ label }}</a>
|
||||
{% endfor %}
|
||||
<a href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=summary" class="rounded-lg border border-slate-300 bg-white px-3 py-2 text-xs font-semibold">Back to Summary</a>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
{% if status_filter=='new_in_current_year' %}
|
||||
<div class="border-b border-slate-200 px-5 py-3 text-xs text-slate-600">
|
||||
{% if show_zero_new %}
|
||||
Zero-balance new Stock Items are currently visible.
|
||||
<a class="font-semibold text-brand-700" href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status=new_in_current_year">Hide zero-balance new Stock Items</a>
|
||||
{% else %}
|
||||
Zero-balance new Stock Items are hidden by default.
|
||||
<a class="font-semibold text-brand-700" href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status=new_in_current_year&show_zero_new=1">Show them</a>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
<form method="post" action="/tools/accounting/opening-balances/apply">
|
||||
<input type="hidden" name="csrf_token" value="{{ csrf_token }}">
|
||||
<input type="hidden" name="client_id" value="{{ selected_client.id }}">
|
||||
<input type="hidden" name="run_id" value="{{ selected_run.id }}">
|
||||
<div class="overflow-x-auto">
|
||||
<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">Apply</th><th class="px-3 py-2">Previous Stock Item</th><th class="px-3 py-2">PY Closing</th><th class="px-3 py-2">Current Stock Item</th><th class="px-3 py-2">CY Opening</th><th class="px-3 py-2">Difference</th><th class="px-3 py-2">Status</th><th class="px-3 py-2">Correction</th></tr></thead>
|
||||
@@ -142,26 +330,35 @@
|
||||
<td class="px-3 py-3"><div>{{ item.previous_closing_qty }} {{ item.previous_unit }}</div><div>₹{{ '%.2f'|format(item.previous_closing_value) }}</div></td>
|
||||
<td class="px-3 py-3"><div class="font-semibold">{{ item.current_name or '—' }}</div><div class="text-slate-500">{{ item.current_group }} · HSN {{ item.current_hsn or '-' }}</div></td>
|
||||
<td class="px-3 py-3"><div>{{ item.current_opening_qty }} {{ item.current_unit }}</div><div>₹{{ '%.2f'|format(item.current_opening_value) }}</div></td>
|
||||
<td class="px-3 py-3"><div>Qty {{ item.quantity_difference }}</div><div>Value ₹{{ '%.2f'|format(item.value_difference) }}</div></td>
|
||||
<td class="px-3 py-3"><div>Qty {{ 0 if item.quantity_difference|abs < 0.000001 else item.quantity_difference }}</div><div>Value ₹{{ '%.2f'|format(0 if item.value_difference|abs < 0.005 else item.value_difference) }}</div></td>
|
||||
<td class="px-3 py-3">{{ item.match_status|replace('_',' ')|title }}{% if item.match_method %}<div class="text-slate-500">{{ item.match_method|replace('_',' ')|title }} · {{ item.confidence }}%</div>{% endif %}</td>
|
||||
<td class="px-3 py-3">{{ item.correction_status|replace('_',' ')|title }}{% if item.correction_note %}<div class="max-w-xs text-slate-500">{{ item.correction_note }}</div>{% endif %}</td>
|
||||
</tr>
|
||||
{% else %}<tr><td colspan="8" class="p-8 text-center text-slate-500">No stock rows for this filter.</td></tr>{% endfor %}
|
||||
{% else %}<tr><td colspan="8" class="p-8 text-center text-slate-500">No Stock Item rows for this category.</td></tr>{% endfor %}
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</section>
|
||||
{% endif %}
|
||||
|
||||
<section class="rounded-2xl border border-red-200 bg-red-50 p-5">
|
||||
<h3 class="font-semibold text-red-900">Apply selected safe corrections directly to current-year Tally</h3>
|
||||
<p class="mt-1 text-sm text-red-800">The Local Agent preflights the current opening against this comparison, applies only unchanged masters, and re-reads each master afterward. Type the confirmation phrase exactly.</p>
|
||||
<div class="mt-3 flex flex-wrap gap-3">
|
||||
<input name="confirm_text" required placeholder="APPLY OPENING BALANCES" class="min-w-[280px] rounded-lg border border-red-300 bg-white px-3 py-2 text-sm">
|
||||
<button class="rounded-lg bg-red-700 px-4 py-2 text-sm font-semibold text-white">Apply Selected to Tally</button>
|
||||
{% if status_filter in ['quantity_difference','value_difference','quantity_and_value_difference'] and stocks %}
|
||||
<div class="border-t border-slate-200 p-4">
|
||||
<div class="flex flex-wrap gap-3">
|
||||
<input name="confirm_text" required placeholder="APPLY OPENING BALANCES" class="min-w-[280px] rounded-lg border border-red-300 px-3 py-2 text-sm">
|
||||
<button class="rounded-lg bg-red-700 px-4 py-2 text-sm font-semibold text-white">Apply Selected Changes</button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
</form>
|
||||
{% endif %}
|
||||
</form>
|
||||
|
||||
{% if pages > 1 %}
|
||||
<div class="flex items-center justify-between border-t border-slate-200 p-4 text-sm">
|
||||
<span>Page {{ page }} of {{ pages }}</span>
|
||||
<div class="flex gap-2">
|
||||
{% if page>1 %}<a class="rounded-lg border border-slate-300 px-3 py-2" href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status={{ status_filter }}&page={{ page-1 }}{% if show_zero_new %}&show_zero_new=1{% endif %}">Previous</a>{% endif %}
|
||||
{% if page<pages %}<a class="rounded-lg border border-slate-300 px-3 py-2" href="?client_id={{ selected_client.id }}&run_id={{ selected_run.id }}&tab=stock&status={{ status_filter }}&page={{ page+1 }}{% if show_zero_new %}&show_zero_new=1{% endif %}">Next</a>{% endif %}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</section>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
|
||||
Reference in New Issue
Block a user