Simplify cash ledger selection using Cash-in-Hand scope
This commit is contained in:
@@ -57,23 +57,27 @@
|
|||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<label class="text-xs font-semibold uppercase text-slate-500">Cash Ledger</label>
|
<label class="text-xs font-semibold uppercase text-slate-500">Cash Ledger</label>
|
||||||
<div class="mt-1 flex gap-2">
|
<select id="cash-ledger-scope" class="mt-1 w-full rounded-xl border-slate-300 text-xs">
|
||||||
|
<option value="cash" selected>Ledgers under Cash-in-Hand</option>
|
||||||
|
<option value="all">All Tally ledgers — manual selection</option>
|
||||||
|
</select>
|
||||||
|
<div class="mt-2 flex gap-2">
|
||||||
<select id="cash-ledger-select" name="cash_ledger_name" class="min-w-0 flex-1 rounded-xl border-slate-300 text-sm" required>
|
<select id="cash-ledger-select" name="cash_ledger_name" class="min-w-0 flex-1 rounded-xl border-slate-300 text-sm" required>
|
||||||
<option value="">Load and confirm cash ledger</option>
|
<option value="">Select Cash ledger</option>
|
||||||
{% if selected_cash_ledger_name %}<option value="{{ selected_cash_ledger_name }}" selected>{{ selected_cash_ledger_name }}</option>{% endif %}
|
{% if selected_cash_ledger_name %}<option value="{{ selected_cash_ledger_name }}" selected>{{ selected_cash_ledger_name }}</option>{% endif %}
|
||||||
</select>
|
</select>
|
||||||
<button type="button" id="cash-load-ledgers" class="rounded-xl border border-slate-300 bg-white px-3 py-2 text-xs font-semibold text-slate-700">Load</button>
|
<button type="button" id="cash-load-ledgers" class="rounded-xl border border-slate-300 bg-white px-3 py-2 text-xs font-semibold text-slate-700">Load Cash Ledgers</button>
|
||||||
<button type="button" id="cash-refresh-ledgers" class="rounded-xl border border-slate-300 bg-white px-3 py-2 text-xs font-semibold text-slate-700">Refresh from Tally</button>
|
<button type="button" id="cash-refresh-ledgers" class="rounded-xl border border-slate-300 bg-white px-3 py-2 text-xs font-semibold text-slate-700">Refresh</button>
|
||||||
</div>
|
</div>
|
||||||
<p id="cash-ledger-help" class="mt-1 text-xs text-slate-500">Loads cached Tally ledgers instantly when available. Refresh from Tally runs safely in the Local Agent background and shows progress here and on the Local Agent dashboard.</p>
|
<p id="cash-ledger-help" class="mt-1 text-xs text-slate-500">By default only ledgers classified under Cash-in-Hand are shown. Choose “All Tally ledgers” only when you need to manually select a ledger that Tally has grouped differently.</p>
|
||||||
<div id="cash-ledger-progress" class="mt-2 hidden rounded-xl border border-sky-200 bg-sky-50 p-3">
|
<div id="cash-ledger-progress" class="mt-2 hidden rounded-xl border border-sky-200 bg-sky-50 p-3">
|
||||||
<div class="flex items-center justify-between text-xs font-semibold text-sky-900"><span id="cash-ledger-progress-stage">Preparing ledger sync…</span><span id="cash-ledger-progress-pct">0%</span></div>
|
<div class="flex items-center justify-between text-xs font-semibold text-sky-900"><span id="cash-ledger-progress-stage">Preparing Cash ledger list…</span><span id="cash-ledger-progress-pct">0%</span></div>
|
||||||
<div class="mt-2 h-2 overflow-hidden rounded-full bg-sky-100"><div id="cash-ledger-progress-bar" class="h-full rounded-full bg-sky-600 transition-all duration-500" style="width:0%"></div></div>
|
<div class="mt-2 h-2 overflow-hidden rounded-full bg-sky-100"><div id="cash-ledger-progress-bar" class="h-full rounded-full bg-sky-600 transition-all duration-500" style="width:0%"></div></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div><label class="text-xs font-semibold uppercase text-slate-500">From</label><input type="date" name="date_from" value="{{ date_from }}" class="mt-1 w-full rounded-xl border-slate-300 text-sm" required></div>
|
<div><label class="text-xs font-semibold uppercase text-slate-500">From</label><input type="date" name="date_from" value="{{ date_from }}" class="mt-1 w-full rounded-xl border-slate-300 text-sm" required></div>
|
||||||
<div><label class="text-xs font-semibold uppercase text-slate-500">To</label><input type="date" name="date_to" value="{{ date_to }}" class="mt-1 w-full rounded-xl border-slate-300 text-sm" required></div>
|
<div><label class="text-xs font-semibold uppercase text-slate-500">To</label><input type="date" name="date_to" value="{{ date_to }}" class="mt-1 w-full rounded-xl border-slate-300 text-sm" required></div>
|
||||||
<div class="md:col-span-2 xl:col-span-5"><button type="button" id="cash-review-button" class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white" {% if not selected_client %}disabled{% endif %}>Extract / Refresh & Analyze</button><p class="mt-2 text-xs text-slate-500">Only vouchers containing the confirmed Cash ledger are stored in the cash-review cache. Extraction runs in the Local Agent background; the same graphical progress is visible here and on the Local Agent dashboard.</p></div>
|
<div class="md:col-span-2 xl:col-span-5"><button type="button" id="cash-review-button" class="rounded-xl bg-brand-600 px-4 py-2 text-sm font-semibold text-white" {% if not selected_client %}disabled{% endif %}>Review Cash Transactions</button><p class="mt-2 text-xs text-slate-500">Select the Tally company, choose a Cash-in-Hand ledger, and review its cash transactions for the selected period. The existing background extraction, threshold analysis and dual VPS/Local Agent progress are preserved.</p></div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@@ -217,7 +221,11 @@
|
|||||||
let activeDateFrom = '';
|
let activeDateFrom = '';
|
||||||
const ledgerButton = document.getElementById('cash-load-ledgers');
|
const ledgerButton = document.getElementById('cash-load-ledgers');
|
||||||
const ledgerSelect = document.getElementById('cash-ledger-select');
|
const ledgerSelect = document.getElementById('cash-ledger-select');
|
||||||
|
const ledgerScope = document.getElementById('cash-ledger-scope');
|
||||||
const ledgerHelp = document.getElementById('cash-ledger-help');
|
const ledgerHelp = document.getElementById('cash-ledger-help');
|
||||||
|
let allLedgerRows = [];
|
||||||
|
let cashLedgerRows = [];
|
||||||
|
let lastLedgerMeta = {ledger_count:0, company_name:'', from_cache:false};
|
||||||
|
|
||||||
const ledgerRefreshButton = document.getElementById('cash-refresh-ledgers');
|
const ledgerRefreshButton = document.getElementById('cash-refresh-ledgers');
|
||||||
const ledgerProgress = document.getElementById('cash-ledger-progress');
|
const ledgerProgress = document.getElementById('cash-ledger-progress');
|
||||||
@@ -226,18 +234,39 @@
|
|||||||
const ledgerProgressStage = document.getElementById('cash-ledger-progress-stage');
|
const ledgerProgressStage = document.getElementById('cash-ledger-progress-stage');
|
||||||
let ledgerPollTimer = null;
|
let ledgerPollTimer = null;
|
||||||
|
|
||||||
function populateLedgers(data) {
|
function renderLedgerOptions() {
|
||||||
const previous = ledgerSelect.value;
|
const previous = ledgerSelect.value;
|
||||||
ledgerSelect.innerHTML = '<option value="">Confirm Cash ledger</option>';
|
const rows = (ledgerScope && ledgerScope.value === 'all') ? allLedgerRows : cashLedgerRows;
|
||||||
(data.ledgers || []).forEach(function(row){
|
ledgerSelect.innerHTML = '<option value="">Select Cash ledger</option>';
|
||||||
|
rows.forEach(function(row){
|
||||||
const opt=document.createElement('option');
|
const opt=document.createElement('option');
|
||||||
opt.value=row.name;
|
opt.value=row.name;
|
||||||
opt.textContent=row.name + (row.parent ? ' — '+row.parent : '') + (row.is_cash_candidate ? ' • Cash candidate' : '');
|
opt.textContent=row.name + (row.parent ? ' — '+row.parent : '') + (row.is_cash_candidate ? ' • Cash-in-Hand' : '');
|
||||||
if ((previous && previous===row.name) || (!previous && row.is_cash_candidate && !ledgerSelect.value)) opt.selected=true;
|
if (previous && previous===row.name) opt.selected=true;
|
||||||
ledgerSelect.appendChild(opt);
|
ledgerSelect.appendChild(opt);
|
||||||
});
|
});
|
||||||
if (!ledgerSelect.value && (data.cash_candidates||[]).length===1) ledgerSelect.value=data.cash_candidates[0].name;
|
if (previous && !rows.some(row => row.name === previous)) ledgerSelect.value='';
|
||||||
ledgerHelp.textContent = String(data.ledger_count || 0)+' ledger(s) ready from '+(data.company_name || 'Tally')+(data.from_cache?' (local cache).':'.')+' Confirm the Cash ledger before extraction.';
|
const company = lastLedgerMeta.company_name || 'Tally';
|
||||||
|
if (ledgerScope && ledgerScope.value === 'all') {
|
||||||
|
ledgerHelp.textContent = String(rows.length)+' of '+String(lastLedgerMeta.ledger_count || allLedgerRows.length)+' ledger(s) available from '+company+'. Select the required ledger manually.';
|
||||||
|
} else if (rows.length) {
|
||||||
|
ledgerHelp.textContent = String(rows.length)+' Cash-in-Hand ledger(s) found in '+company+'. Select the ledger whose transactions should be reviewed.';
|
||||||
|
} else if (allLedgerRows.length) {
|
||||||
|
ledgerHelp.textContent = 'No Cash-in-Hand ledger was identified from Tally grouping. Choose “All Tally ledgers — manual selection” to select the required ledger.';
|
||||||
|
} else {
|
||||||
|
ledgerHelp.textContent = 'No ledgers are available yet for the selected Tally company.';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function populateLedgers(data) {
|
||||||
|
allLedgerRows = Array.isArray(data.ledgers) ? data.ledgers.slice() : [];
|
||||||
|
cashLedgerRows = Array.isArray(data.cash_candidates) ? data.cash_candidates.slice() : allLedgerRows.filter(row => row.is_cash_candidate);
|
||||||
|
lastLedgerMeta = {
|
||||||
|
ledger_count: Number(data.ledger_count || allLedgerRows.length || 0),
|
||||||
|
company_name: String(data.company_name || ''),
|
||||||
|
from_cache: Boolean(data.from_cache)
|
||||||
|
};
|
||||||
|
renderLedgerOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
function updateLedgerProgress(job) {
|
function updateLedgerProgress(job) {
|
||||||
@@ -299,11 +328,21 @@
|
|||||||
if (ledgerButton) ledgerButton.addEventListener('click', function(){loadCashLedgers(false);});
|
if (ledgerButton) ledgerButton.addEventListener('click', function(){loadCashLedgers(false);});
|
||||||
if (ledgerRefreshButton) ledgerRefreshButton.addEventListener('click', function(){loadCashLedgers(true);});
|
if (ledgerRefreshButton) ledgerRefreshButton.addEventListener('click', function(){loadCashLedgers(true);});
|
||||||
const companySelect = document.getElementById('cash-tally-company');
|
const companySelect = document.getElementById('cash-tally-company');
|
||||||
|
if (ledgerScope) ledgerScope.addEventListener('change', function(){ renderLedgerOptions(); });
|
||||||
if (companySelect) companySelect.addEventListener('change', function(){
|
if (companySelect) companySelect.addEventListener('change', function(){
|
||||||
ledgerSelect.innerHTML = '<option value="">Load and confirm cash ledger</option>';
|
allLedgerRows = []; cashLedgerRows = []; lastLedgerMeta = {ledger_count:0, company_name:'', from_cache:false};
|
||||||
ledgerHelp.textContent = this.value ? 'Company changed. Click Load to use that company's cached ledgers, or Refresh from Tally to re-sync.' : 'Select an open Tally company first.';
|
ledgerSelect.innerHTML = '<option value="">Select Cash ledger</option>';
|
||||||
ledgerProgress.classList.add('hidden');
|
ledgerProgress.classList.add('hidden');
|
||||||
|
if (this.value) {
|
||||||
|
ledgerHelp.textContent = 'Loading Cash-in-Hand ledgers for the selected Tally company…';
|
||||||
|
loadCashLedgers(false);
|
||||||
|
} else {
|
||||||
|
ledgerHelp.textContent = 'Select an open Tally company first.';
|
||||||
|
}
|
||||||
});
|
});
|
||||||
|
if (companySelect && companySelect.value) {
|
||||||
|
window.setTimeout(function(){ loadCashLedgers(false); }, 250);
|
||||||
|
}
|
||||||
|
|
||||||
function show() {
|
function show() {
|
||||||
overlay.classList.remove('hidden');
|
overlay.classList.remove('hidden');
|
||||||
@@ -373,7 +412,7 @@
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (job.status === 'paused' || job.status === 'failed') {
|
if (job.status === 'paused' || job.status === 'failed') {
|
||||||
fail(job.error || 'Tally extraction paused. Restart/verify TallyPrime and click Extract / Refresh & Analyze again to resume.');
|
fail(job.error || 'Tally extraction paused. Restart/verify TallyPrime and click Review Cash Transactions again to resume.');
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
pollTimer = window.setTimeout(() => poll(jobId, clientId, dateFrom, tallyGuid, dateTo), 2000);
|
pollTimer = window.setTimeout(() => poll(jobId, clientId, dateFrom, tallyGuid, dateTo), 2000);
|
||||||
|
|||||||
Reference in New Issue
Block a user