diff --git a/app/modules/accounting/templates/accounting/cash_payment_review.html b/app/modules/accounting/templates/accounting/cash_payment_review.html index ae562c9..b4bfc6a 100644 --- a/app/modules/accounting/templates/accounting/cash_payment_review.html +++ b/app/modules/accounting/templates/accounting/cash_payment_review.html @@ -57,23 +57,27 @@
-
+ +
- - + +
-

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.

+

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.

-

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.

+

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.

@@ -217,7 +221,11 @@ let activeDateFrom = ''; const ledgerButton = document.getElementById('cash-load-ledgers'); const ledgerSelect = document.getElementById('cash-ledger-select'); + const ledgerScope = document.getElementById('cash-ledger-scope'); 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 ledgerProgress = document.getElementById('cash-ledger-progress'); @@ -226,18 +234,39 @@ const ledgerProgressStage = document.getElementById('cash-ledger-progress-stage'); let ledgerPollTimer = null; - function populateLedgers(data) { + function renderLedgerOptions() { const previous = ledgerSelect.value; - ledgerSelect.innerHTML = ''; - (data.ledgers || []).forEach(function(row){ + const rows = (ledgerScope && ledgerScope.value === 'all') ? allLedgerRows : cashLedgerRows; + ledgerSelect.innerHTML = ''; + rows.forEach(function(row){ const opt=document.createElement('option'); opt.value=row.name; - opt.textContent=row.name + (row.parent ? ' — '+row.parent : '') + (row.is_cash_candidate ? ' • Cash candidate' : ''); - if ((previous && previous===row.name) || (!previous && row.is_cash_candidate && !ledgerSelect.value)) opt.selected=true; + opt.textContent=row.name + (row.parent ? ' — '+row.parent : '') + (row.is_cash_candidate ? ' • Cash-in-Hand' : ''); + if (previous && previous===row.name) opt.selected=true; ledgerSelect.appendChild(opt); }); - if (!ledgerSelect.value && (data.cash_candidates||[]).length===1) ledgerSelect.value=data.cash_candidates[0].name; - 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.'; + if (previous && !rows.some(row => row.name === previous)) ledgerSelect.value=''; + 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) { @@ -299,11 +328,21 @@ if (ledgerButton) ledgerButton.addEventListener('click', function(){loadCashLedgers(false);}); if (ledgerRefreshButton) ledgerRefreshButton.addEventListener('click', function(){loadCashLedgers(true);}); const companySelect = document.getElementById('cash-tally-company'); + if (ledgerScope) ledgerScope.addEventListener('change', function(){ renderLedgerOptions(); }); if (companySelect) companySelect.addEventListener('change', function(){ - ledgerSelect.innerHTML = ''; - 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.'; + allLedgerRows = []; cashLedgerRows = []; lastLedgerMeta = {ledger_count:0, company_name:'', from_cache:false}; + ledgerSelect.innerHTML = ''; 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() { overlay.classList.remove('hidden'); @@ -373,7 +412,7 @@ return; } 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; } pollTimer = window.setTimeout(() => poll(jobId, clientId, dateFrom, tallyGuid, dateTo), 2000);