bep40 commited on
Commit
b6886d9
·
verified ·
1 Parent(s): 30b624b

Upload order-store.js

Browse files
Files changed (1) hide show
  1. order-store.js +32 -13
order-store.js CHANGED
@@ -1,9 +1,13 @@
1
  /**
2
- * V.AI STUDIO — Order Store v19.2
 
 
 
 
 
3
  *
4
  * CHANGES from v19.1:
5
  * - FIX: AbortController 8s timeout cho syncFromServer tránh treo UI khi bot ngủ
6
- * - FIX: Skip BẢO HÀNH X NĂM/giao thứ X notes khỏi fees/phụ phí
7
  *
8
  * CHANGES from v18:
9
  * - ADD PRODUCT TO ORDER: Nút "➕ Thêm SP" trong modal sửa đơn
@@ -66,11 +70,11 @@ function syncFromServer(){
66
  });
67
  if(added>0){
68
  saveOrders(localOrders);
69
- console.log('[OS v19.2] ☁️ Synced '+added+' orders from server. Total local: '+localOrders.length);
70
  }
71
  }).catch(function(e){
72
- if(e.name==='AbortError'){console.log('[OS v19.2] Server sync timeout (8s) — bot sleeping, skip');}
73
- else{console.log('[OS v19.2] Server sync skip (bot may be sleeping)');}
74
  });
75
  }
76
  // Sync from server 3s after page load (give bot time to wake up)
@@ -86,7 +90,7 @@ function processQueue(){
86
  var q=getQueue();if(!q.length)return;
87
  var item=q[0];
88
  fetch(KETOAN_API+item.endpoint,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(item.payload)})
89
- .then(function(r){if(r.ok){q.shift();saveQueue(q);console.log('[OS v19.2] Queue sync OK: '+item.endpoint+' ('+q.length+' remaining)');if(q.length)setTimeout(processQueue,2000);}else throw new Error('HTTP '+r.status);})
90
  .catch(function(){item.attempts=(item.attempts||0)+1;if(item.attempts>50){q.shift();}saveQueue(q);});
91
  }
92
  setInterval(processQueue,30000);
@@ -187,11 +191,16 @@ function parsePrompt(text){
187
  // If rest is just a number/unit, skip
188
  if(textAfterBrand.match(/^[\d.,\s%(k|tr|trieu|m|đ|vnd)]+$/i)) return;
189
  }
190
- // ===== FIX v19.2: Skip note patterns (BẢO HÀNH X NĂM, giao thứ X) =====
191
- if(lo.match(/bao.hanh\s*\d+\s*(nam|thang)/)||lo.match(/giao\s+(thu|ngay)\s*\d+/)||lo.match(/\b(nam|thang)\s*(bao.hanh)/))return;
192
- // Fallback: line with number
 
 
 
 
 
193
  var m=lo.match(/([\d.,]+)\s*(k|tr|trieu|m|nghin)?/);
194
- if(m){var amt2=parseFloat(m[1].replace(/\./g,'').replace(',','.'));var u3=(m[2]||'').toLowerCase();if(u3==='k'||u3==='nghin')amt2*=1000;if(u3==='tr'||u3==='trieu'||u3==='m')amt2*=1000000;if(amt2>0){var lb=line.replace(m[0],'').trim();if(!lb||lb.length<2)lb='Phụ phí';fees.push({label:lb,amount:amt2});}}
195
  });
196
  return{fees:fees,deposit:deposit,discountPercent:discountPercent,note:note,itemDiscounts:itemDiscounts};
197
  }
@@ -221,6 +230,8 @@ function openSearchModal(){var old=document.getElementById('vai-order-search-mod
221
 
222
  function openOrderDetail(order){var old=document.getElementById('vai-order-detail-modal');if(old)old.remove();order=JSON.parse(JSON.stringify(order));var ov=document.createElement('div');ov.id='vai-order-detail-modal';ov.style.cssText='position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:10000;display:flex;align-items:flex-start;justify-content:center;padding:16px;overflow-y:auto';ov.onclick=function(e){if(e.target===ov)ov.remove();};document.body.appendChild(ov);var modal=document.createElement('div');modal.style.cssText='background:#fff;border-radius:16px;max-width:750px;width:100%;max-height:92vh;overflow-y:auto';ov.appendChild(modal);
223
  var _searchOpen=false;
 
 
224
  function addProductToOrder(product){
225
  var pn=product.priceNum||product.pn||0;
226
  var item={name:product.name||product.n||'',model:product.sku||product.model||product.mod||'',brand:product.brand||'',image:product.image||product.img||product.i||'',specs:product.specs||'',info:product.info||product.thong_tin||'',dim_info:product.dim_info||product.dimension_info||'',qty:1,price:pn,discPrice:pn,total:pn,note:''};
@@ -239,6 +250,8 @@ function openOrderDetail(order){var old=document.getElementById('vai-order-detai
239
  var db=[];if(typeof D!=='undefined'&&Array.isArray(D))db=D;if(typeof VAI_URL_ADDED_PRODUCTS!=='undefined'&&Array.isArray(VAI_URL_ADDED_PRODUCTS))db=db.concat(VAI_URL_ADDED_PRODUCTS);
240
  var nq=nrm(q);var terms=nq.split(/\s+/).filter(function(t){return t.length>1;});
241
  var scored=[];
 
 
242
  for(var i=0;i<db.length;i++){
243
  var p=db[i];if(!p)continue;
244
  var name=nrm(p.name||p.n||'');var sku=nrm(p.sku||p.model||p.mod||'');var brand=nrm(p.brand||'');
@@ -339,9 +352,15 @@ function openOrderDetail(order){var old=document.getElementById('vai-order-detai
339
  // Close search panel
340
  var closeSpBtn=document.getElementById('od-sp-close');
341
  if(closeSpBtn){closeSpBtn.onclick=function(){_searchOpen=false;render();};}
342
- // Search input
343
  var searchInput=document.getElementById('od-sp-search');
344
- if(searchInput){searchInput.oninput=function(){renderSearchResults();};searchInput.onkeydown=function(e){if(e.key==='Escape'){_searchOpen=false;render();}};}
 
 
 
 
 
 
345
  // Render search results if panel is open
346
  if(_searchOpen){renderSearchResults();}
347
  function cc(){order.customer=document.getElementById('od-name').value;order.phone=document.getElementById('od-phone').value;order.addr=document.getElementById('od-addr').value;}
@@ -373,5 +392,5 @@ var _mO=new MutationObserver(function(){setTimeout(injectMaKHToQuote,500);});_mO
373
 
374
  window.VAI_ORDERS={save:saveCurrentOrder,search:searchOrders,openSearch:openSearchModal,openDetail:openOrderDetail,getAll:getOrders,getByCode:function(c){return getOrders().find(function(o){return o.code===c;});},add:addOrder,delete:deleteOrder,confirm:confirmOrder,unconfirm:unconfirmOrder,toVAIData:orderToVAIData,loadKH:loadKhachHang,findKH:findKH,processQueue:processQueue,syncFromServer:syncFromServer};
375
  var qLen=getQueue().length;
376
- console.log('[OS v19.2] '+getOrders().length+' orders'+(qLen?' | ⏳ '+qLen+' pending sync':'')+' | ☁️ Server sync enabled | ➕ Add product to order enabled | 🛠️ Fixed CK/price lines in fees | ⏱️ AbortController 8s | 🚫 Skip BH/giao thứ X notes');
377
  })();
 
1
  /**
2
+ * V.AI STUDIO — Order Store v19.3
3
+ *
4
+ * CHANGES from v19.2:
5
+ * - FIX: searchProducts debounce 200ms → không treo UI khi gõ tìm SP
6
+ * - FIX: parsePrompt fallback không đẩy text có số vào notes, thành Phụ phí
7
+ * - FIX: Vẫn skip BẢO HÀNH X NĂM/giao thứ X notes khỏi phụ phí
8
  *
9
  * CHANGES from v19.1:
10
  * - FIX: AbortController 8s timeout cho syncFromServer tránh treo UI khi bot ngủ
 
11
  *
12
  * CHANGES from v18:
13
  * - ADD PRODUCT TO ORDER: Nút "➕ Thêm SP" trong modal sửa đơn
 
70
  });
71
  if(added>0){
72
  saveOrders(localOrders);
73
+ console.log('[OS v19.3] ☁️ Synced '+added+' orders from server. Total local: '+localOrders.length);
74
  }
75
  }).catch(function(e){
76
+ if(e.name==='AbortError'){console.log('[OS v19.3] Server sync timeout (8s) — bot sleeping, skip');}
77
+ else{console.log('[OS v19.3] Server sync skip (bot may be sleeping)');}
78
  });
79
  }
80
  // Sync from server 3s after page load (give bot time to wake up)
 
90
  var q=getQueue();if(!q.length)return;
91
  var item=q[0];
92
  fetch(KETOAN_API+item.endpoint,{method:'POST',headers:{'Content-Type':'application/json'},body:JSON.stringify(item.payload)})
93
+ .then(function(r){if(r.ok){q.shift();saveQueue(q);console.log('[OS v19.3] Queue sync OK: '+item.endpoint+' ('+q.length+' remaining)');if(q.length)setTimeout(processQueue,2000);}else throw new Error('HTTP '+r.status);})
94
  .catch(function(){item.attempts=(item.attempts||0)+1;if(item.attempts>50){q.shift();}saveQueue(q);});
95
  }
96
  setInterval(processQueue,30000);
 
191
  // If rest is just a number/unit, skip
192
  if(textAfterBrand.match(/^[\d.,\s%(k|tr|trieu|m|đ|vnd)]+$/i)) return;
193
  }
194
+ // ===== FIX v19.3: Skip note patterns nhưng KHÔNG chặn fee detection =====
195
+ var isNotePattern=false;
196
+ if(lo.match(/bao.hanh\s*\d+\s*(nam|thang)/)){isNotePattern=true;}
197
+ if(!isNotePattern&&lo.match(/giao\s+(thu|ngay)\s*\d+/)){isNotePattern=true;}
198
+ if(!isNotePattern&&lo.match(/\b(nam|thang)\s*(bao.hanh)/)){isNotePattern=true;}
199
+ if(isNotePattern)return;
200
+ // === End note skip ===
201
+ // Fallback: line with number → Phụ phí (không đẩy vào notes)
202
  var m=lo.match(/([\d.,]+)\s*(k|tr|trieu|m|nghin)?/);
203
+ if(m){var amt2=parseFloat(m[1].replace(/\./g,'').replace(',','.'));var u3=(m[2]||'').toLowerCase();if(u3==='k'||u3==='nghin')amt2*=1000;if(u3==='tr'||u3==='trieu'||u3==='m')amt2*=1000000;if(amt2>0){var lb=line.replace(m[0],'').trim();if(!lb||lb.length<2)lb='Phụ phí';else lb='Phụ phí';fees.push({label:lb,amount:amt2});}}
204
  });
205
  return{fees:fees,deposit:deposit,discountPercent:discountPercent,note:note,itemDiscounts:itemDiscounts};
206
  }
 
230
 
231
  function openOrderDetail(order){var old=document.getElementById('vai-order-detail-modal');if(old)old.remove();order=JSON.parse(JSON.stringify(order));var ov=document.createElement('div');ov.id='vai-order-detail-modal';ov.style.cssText='position:fixed;inset:0;background:rgba(0,0,0,.6);z-index:10000;display:flex;align-items:flex-start;justify-content:center;padding:16px;overflow-y:auto';ov.onclick=function(e){if(e.target===ov)ov.remove();};document.body.appendChild(ov);var modal=document.createElement('div');modal.style.cssText='background:#fff;border-radius:16px;max-width:750px;width:100%;max-height:92vh;overflow-y:auto';ov.appendChild(modal);
232
  var _searchOpen=false;
233
+ // ===== FIX v19.3: Debounce cho searchProducts =====
234
+ var _searchDebounceTimer=null;
235
  function addProductToOrder(product){
236
  var pn=product.priceNum||product.pn||0;
237
  var item={name:product.name||product.n||'',model:product.sku||product.model||product.mod||'',brand:product.brand||'',image:product.image||product.img||product.i||'',specs:product.specs||'',info:product.info||product.thong_tin||'',dim_info:product.dim_info||product.dimension_info||'',qty:1,price:pn,discPrice:pn,total:pn,note:''};
 
250
  var db=[];if(typeof D!=='undefined'&&Array.isArray(D))db=D;if(typeof VAI_URL_ADDED_PRODUCTS!=='undefined'&&Array.isArray(VAI_URL_ADDED_PRODUCTS))db=db.concat(VAI_URL_ADDED_PRODUCTS);
251
  var nq=nrm(q);var terms=nq.split(/\s+/).filter(function(t){return t.length>1;});
252
  var scored=[];
253
+ // Giới hạn quét: chỉ quét thực sự khi có terms
254
+ if(!terms.length)return[];
255
  for(var i=0;i<db.length;i++){
256
  var p=db[i];if(!p)continue;
257
  var name=nrm(p.name||p.n||'');var sku=nrm(p.sku||p.model||p.mod||'');var brand=nrm(p.brand||'');
 
352
  // Close search panel
353
  var closeSpBtn=document.getElementById('od-sp-close');
354
  if(closeSpBtn){closeSpBtn.onclick=function(){_searchOpen=false;render();};}
355
+ // Search input v19.3: debounce 200ms để tránh treo UI
356
  var searchInput=document.getElementById('od-sp-search');
357
+ if(searchInput){
358
+ searchInput.oninput=function(){
359
+ if(_searchDebounceTimer)clearTimeout(_searchDebounceTimer);
360
+ _searchDebounceTimer=setTimeout(function(){renderSearchResults();},200);
361
+ };
362
+ searchInput.onkeydown=function(e){if(e.key==='Escape'){_searchOpen=false;render();}};
363
+ }
364
  // Render search results if panel is open
365
  if(_searchOpen){renderSearchResults();}
366
  function cc(){order.customer=document.getElementById('od-name').value;order.phone=document.getElementById('od-phone').value;order.addr=document.getElementById('od-addr').value;}
 
392
 
393
  window.VAI_ORDERS={save:saveCurrentOrder,search:searchOrders,openSearch:openSearchModal,openDetail:openOrderDetail,getAll:getOrders,getByCode:function(c){return getOrders().find(function(o){return o.code===c;});},add:addOrder,delete:deleteOrder,confirm:confirmOrder,unconfirm:unconfirmOrder,toVAIData:orderToVAIData,loadKH:loadKhachHang,findKH:findKH,processQueue:processQueue,syncFromServer:syncFromServer};
394
  var qLen=getQueue().length;
395
+ console.log('[OS v19.3] '+getOrders().length+' orders'+(qLen?' | ⏳ '+qLen+' pending sync':'')+' | ☁️ Server sync enabled | ➕ Add product to order enabled | 🛠️ Debounce search 200ms | 🚫 Skip BH/giao thứ X notes');
396
  })();