sale order
SAP-ERP Portal CI/CD / build (push) Successful in 3m57s

This commit is contained in:
John
2026-10-05 18:45:17 +05:30
parent e725a6571b
commit eead8f5ffd
129 changed files with 14252 additions and 452 deletions
+14 -6
View File
@@ -155,6 +155,7 @@ let _modalOpen=false;
let _readyOrders=[];
let _readyLoading=false;
let _page=0,_pageSize=20,_total=null,_rawCount=0,_search=''; // ready-orders pagination + server search
let _dateFrom='',_dateTo=''; // Due Date range, sent to the server (see loadReadyOrders())
let _viewOrderType=CONSUMABLE_ONLY_USER?'consumable':''; // '' = all, 'consumable' = Consumable Orders only, 'regular' = everything else
let _closeRequireFullQty=true; // admin setting (Settings → closeRequireFullQty) — fetched in init()
let _localStatusByEntry={}; // sapAbsEntry → local status (to exempt REJECTED orders from the full-qty gate)
@@ -200,7 +201,8 @@ async function loadReadyOrders(resetPage){
// hide every single one of their orders.
const readyParam=CONSUMABLE_ONLY_USER?'':'&readyToClose=1';
try{
const r=await api('GET',`/sap/production-orders?status=Released${readyParam}&top=${_pageSize}&skip=${_page*_pageSize}&company=${encodeURIComponent(_co)}${searchQ}${_viewOrderType?'&orderType='+_viewOrderType:''}`);
const dateQ=(_dateFrom?`&dateFrom=${_dateFrom}`:'')+(_dateTo?`&dateTo=${_dateTo}`:'');
const r=await api('GET',`/sap/production-orders?status=Released${readyParam}&top=${_pageSize}&skip=${_page*_pageSize}&company=${encodeURIComponent(_co)}${searchQ}${dateQ}${_viewOrderType?'&orderType='+_viewOrderType:''}`);
_rawCount=(r.data||[]).length;
_readyOrders=(r.data||[]);
_total=(typeof r.total==='number')?r.total:null;
@@ -263,11 +265,15 @@ function _doRender(){
<div class="po-top"><span class="po-code">${esc(o.ItemNo)}</span>${badge}${consBadge}</div>
<div class="po-icon">🔒</div>
<div class="po-name" title="${esc(o.ProductDescription||'')}">${esc(o.ProductDescription||'-')}</div>
<div class="po-meta"><span>#${o.DocumentNumber||o.AbsoluteEntry} · Qty <b>${o.PlannedQuantity}</b></span><span>Done <b>${o.CompletedQuantity||0}</b> · WH <b>${esc(o.Warehouse||'-')}</b></span></div>
<div class="po-meta"><span>#${o.DocumentNumber||o.AbsoluteEntry} · Qty <b>${o.PlannedQuantity}</b></span><span>Done <b>${o.CompletedQuantity||0}</b> · WH <b>${esc(o.Warehouse||'-')}</b>${o.DueDate?` · Due <b>${new Date(o.DueDate).toLocaleDateString('en-IN',{day:'2-digit',month:'short',year:'2-digit'})}</b>`:''}</span></div>
${(o.WoNo||o.BatchNumber)?`<div class="po-meta"><span>${o.WoNo?`WO <b>${esc(o.WoNo)}</b>`:''}${o.WoNo&&o.BatchNumber?' · ':''}${o.BatchNumber?`Batch <b>${esc(o.BatchNumber)}</b>`:''}</span></div>`:''}
</div>`;}).join('')}</div>`;
const searchRow=`<div style="display:flex;gap:6px;margin-bottom:10px">
<input class="fi fi-mono" id="rp-search" value="${esc(_search)}" placeholder="Search item code, description, document no, order no, WO no or batch no…" style="font-size:12px;flex:1"/>
const searchRow=`<div style="display:flex;gap:6px;margin-bottom:10px;flex-wrap:wrap">
<input class="fi fi-mono" id="rp-search" value="${esc(_search)}" placeholder="Search item code, description, document no, order no, WO no or batch no…" style="font-size:12px;flex:1;min-width:220px"/>
<span style="font-size:10px;color:var(--text3);text-transform:uppercase;letter-spacing:.4px;align-self:center">Due</span>
<input class="fi" id="rp-datefrom" type="date" value="${esc(_dateFrom)}" style="font-size:12px"/>
<span style="font-size:11px;color:var(--text3);align-self:center">to</span>
<input class="fi" id="rp-dateto" type="date" value="${esc(_dateTo)}" style="font-size:12px"/>
<button class="btn" id="rp-load" style="padding:6px 16px;font-size:11px;background:var(--amber);color:#fff;white-space:nowrap">Search</button>
</div>`;
const typeRow=CONSUMABLE_ONLY_USER
@@ -276,7 +282,7 @@ function _doRender(){
<span style="font-size:10px;color:var(--text3);text-transform:uppercase;letter-spacing:.4px;margin-right:2px">Type</span>
${[['','All'],['regular','Regular PWO'],['consumable','Consumable']].map(([v,l])=>`<button class="btn" style="padding:5px 11px;font-size:11px;${_viewOrderType===v?'background:rgba(159,90,253,.15);color:#9f5afd;border:1px solid rgba(159,90,253,.4)':'background:var(--surface2);color:var(--text3);border:1px solid var(--border2)'}" data-vot="${v}">${l}</button>`).join('')}
</div>`:'';
c2b.innerHTML=`<div class="card-hd"><span class="ico"></span> Orders Ready to Close<span class="right">${_readyOrders.length}</span></div>
c2b.innerHTML=`<div class="card-hd"><span class="ico"></span> Orders Ready to Close<span class="right">${_total!=null?_total:_readyOrders.length}</span></div>
<div class="card-bd">
<div style="font-size:11px;color:var(--text3);margin-bottom:10px">${CONSUMABLE_ONLY_USER?'Consumable Orders — Release → Issue → Close only, no Receipt required.':'Only Released orders that are fully issued and fully received are listed here (per Admin → System Settings). An order missing either isn\'t shown — issue or receive the rest first, then it appears here.'}</div>
${searchRow}${typeRow}${gridBody}${renderPager()}</div>`;
@@ -290,6 +296,8 @@ function _doRender(){
q('#rp-search')&&(q('#rp-search').oninput=function(){_search=this.value;});
q('#rp-search')&&(q('#rp-search').onkeydown=function(e){if(e.key==='Enter'){e.preventDefault();loadReadyOrders(true);}});
q('#rp-load')&&(q('#rp-load').onclick=()=>loadReadyOrders(true));
q('#rp-datefrom')&&(q('#rp-datefrom').onchange=function(){_dateFrom=this.value;loadReadyOrders(true);});
q('#rp-dateto')&&(q('#rp-dateto').onchange=function(){_dateTo=this.value;loadReadyOrders(true);});
document.querySelectorAll('[data-vot]').forEach(b=>b.onclick=function(){_viewOrderType=this.dataset.vot;loadReadyOrders(true);});
q('#rp-prev')&&(q('#rp-prev').onclick=()=>{if(_page>0){_page--;loadReadyOrders();}});
q('#rp-next')&&(q('#rp-next').onclick=()=>{if(pagerHasNext()){_page++;loadReadyOrders();}});
@@ -437,6 +445,6 @@ window.addEventListener('hashchange',()=>{
}
});
</script>
<script src="/sidebar.js?v=25"></script>
<script src="/sidebar.js?v=31"></script>
</body>
</html>