bep40 commited on
Commit
bfeb2f8
·
verified ·
1 Parent(s): f4d485c

Upload qr-payment-v1043-FIXED.js

Browse files
Files changed (1) hide show
  1. qr-payment-v1043-FIXED.js +54 -25
qr-payment-v1043-FIXED.js CHANGED
@@ -34,6 +34,7 @@ function getCustomerName(){var sels=['#quoteName','#quoteCustomerName','#checkou
34
  function getEffectiveOrderCode(){var n=getCustomerName();if(n)return generateOrderCode(n);var h=window.location.hash;if(h&&h.length>1){var c=h.substring(1);if(/^VAS[A-Z0-9]{3,}$/.test(c))return c;}return generateOrderCode('');}
35
  function getQRUrl(a,c){return'https://img.vietqr.io/image/'+BANK_ID+'-'+BANK_ACCOUNT+'-compact2.png?amount='+(Math.round(a)||0)+'&addInfo='+encodeURIComponent(c||'VAISTUDIO')+'&accountName='+encodeURIComponent(BANK_NAME);}
36
  function fmt(n){if(!n||isNaN(n))return'0đ';return Number(n).toLocaleString('vi-VN')+'đ';}
 
37
  function compactKey(s){return stripDiacritics(String(s||'')).toLowerCase().replace(/[^a-z0-9]/g,'');}
38
  function itemKeys(it){var arr=[];['model','sku','code','ma','name'].forEach(function(k){if(it&&it[k])arr.push(compactKey(it[k]));});if(it&&it.name){String(it.name).split('|').forEach(function(x){arr.push(compactKey(x));});}return arr.filter(function(x){return x&&x.length>=3;});}
39
  function matchItemDiscount(it,itemDiscounts){itemDiscounts=itemDiscounts||{};var keys=itemKeys(it);for(var i=0;i<keys.length;i++){var k=keys[i];if(itemDiscounts[k])return itemDiscounts[k];}for(var code in itemDiscounts){for(var j=0;j<keys.length;j++){var kk=keys[j];if(code.length>=3&&kk.length>=3&&(kk.indexOf(code)!==-1||code.indexOf(kk)!==-1))return itemDiscounts[code];}}return 0;}
@@ -51,7 +52,7 @@ function parsePrompt(text){
51
 
52
  if(Object.keys(itemDiscounts).length&&line.match(/\\b[A-Za-z]{1,8}[A-Za-z0-9._\-\/]{1,30}\\d[A-Za-z0-9._\-\/]*\\b/i)&&line.match(/\\b(ck|chiết khấu|chiet khau|giảm|giam|discount)\\b/i))return;
53
 
54
- // CK
55
  if(line.match(/^(ck|chiết khấu|chiet khau|giảm|giam|discount)/i)){
56
  discount=line;
57
  var ckm=line.match(/([\d.,]+)\\s*(%)?/);
@@ -61,6 +62,13 @@ function parsePrompt(text){
61
  }
62
  return;
63
  }
 
 
 
 
 
 
 
64
 
65
  // Cọc
66
  if(line.match(/cọc|coc|deposit/i)){
@@ -75,8 +83,15 @@ function parsePrompt(text){
75
  return;
76
  }
77
 
 
 
 
 
 
 
 
78
  // Phí giao hàng, lắp đặt - FIX QUAN TRỌNG
79
- var feeMatch=line.match(/([\d.,]+)\\s*(k|K|nghìn|nghin|triệu|tr|đ|d|vnd)?/);
80
  if(feeMatch){
81
  var amt=parseFloat(feeMatch[1].replace(/\\./g,'').replace(',','.'));
82
  var u=(feeMatch[2]||'').toLowerCase();
@@ -192,7 +207,7 @@ function injectToModal(){
192
  if(parsed.fees.length){
193
  html+='<div style="padding:8px 12px;background:#fffbeb;border-radius:6px;border:1px solid #fde68a;margin-bottom:8px"><div style="font-weight:700;color:#92400e;font-size:12px;margin-bottom:4px">PHỤ PHÍ</div>';
194
  parsed.fees.forEach(function(f){
195
- html+='<div style="display:flex;justify-content:space-between;padding:2px 0"><span>'+f.label+'</span><span style="font-weight:700">'+fmt(f.amount)+'</span></div>';
196
  });
197
  html+='</div>';
198
  }
@@ -243,7 +258,7 @@ function buildQuoteHTML(d,code,qrUrl){
243
  var feeRows='';
244
  if(d.fees&&d.fees.length){
245
  d.fees.forEach(function(f){
246
- feeRows+='<tr style="background:#fffbeb"><td colspan="8" style="padding:5px 10px;font-size:11px;color:#92400e">⊕ '+f.label+'</td><td style="padding:5px 4px;text-align:right;font-size:11px;font-weight:700">'+fmt(f.amount)+'</td></tr>';
247
  });
248
  }
249
  return '<div style="display:flex;align-items:center;gap:10px">'
@@ -266,7 +281,7 @@ function buildQuoteHTML(d,code,qrUrl){
266
  +'<span style="color:#fff;font-weight:800">TỔNG CỘNG</span>'
267
  +'<span style="color:#f0b840;font-weight:900;margin-left:10px">'+fmt(d.grandTotal)+'</span>'
268
  +'</div>'
269
- +(d.deposit>0?'<div style="margin-top:6px;padding:6px 12px;background:#f0fdf4;font-size:12px"><span>Cọc: <b>'+fmt(d.deposit)+'</b></span> | <span>Còn lại: <b style="color:#dc2626">'+fmt(d.remaining)+'</b></span></div>':'');
270
  }
271
 
272
  function buildDeliveryHTML(qd,code){
@@ -374,7 +389,7 @@ async function _doExportDeliveryPDF(qd,code){
374
  pdf.save('GH-'+code+'.xlsx');
375
  }
376
 
377
- // ===== EXPORT EXCEL - FIX BAO GỒM PHÍ =====
378
  async function _doExportExcel(d,qd,code,qrUrl){
379
  var MONEY_FMT='#,##0"đ"';
380
  var NUM_FMT='#,##0';
@@ -383,19 +398,19 @@ async function _doExportExcel(d,qd,code,qrUrl){
383
  ws.views=[{showGridLines:false}];
384
  ws.columns=[{width:5},{width:11},{width:28},{width:13},{width:20},{width:6},{width:13},{width:13},{width:15},{width:14}];
385
 
386
- ws.mergeCells('A3:J3');
387
- ws.getCell('A3').value='BẢNG BÁO GIÁ';
388
- ws.getCell('A3').font={bold:true,size:18,color:{argb:'FFDB9815'}};
389
- ws.getCell('A3').alignment={horizontal:'center'};
390
 
391
- ws.getCell('A5').value='Khách hàng:';ws.mergeCells('B5:E5');ws.getCell('B5').value=qd.customer?qd.customer.name:'';
392
- ws.getCell('H5').value='Mã đơn:';ws.mergeCells('I5:J5');ws.getCell('I5').value=code;
393
- ws.getCell('A6').value='SĐT:';ws.mergeCells('B6:E6');ws.getCell('B6').value=qd.customer?qd.customer.phone:'';
394
- ws.getCell('H6').value='Ngày:';ws.mergeCells('I6:J6');ws.getCell('I6').value=qd.customer?qd.customer.date:'';
395
- ws.getCell('A7').value='Email:';ws.mergeCells('B7:E7');ws.getCell('B7').value=qd.customer?qd.customer.email:'';
396
- ws.getCell('A8').value='Địa chỉ:';ws.mergeCells('B8:J8');ws.getCell('B8').value=qd.customer?qd.customer.addr:'';
397
 
398
- var hr=ws.getRow(10);
399
  ['STT','Hình','Tên sản phẩm','Mã SP','Thông tin','SL','Đơn giá','Giá CK','Thành tiền','Ghi chú'].forEach(function(h,i){
400
  var c=hr.getCell(i+1);
401
  c.value=h;
@@ -403,7 +418,7 @@ async function _doExportExcel(d,qd,code,qrUrl){
403
  c.fill={type:'pattern',pattern:'solid',fgColor:{argb:'FF003F62'};
404
  });
405
 
406
- var cr=11,firstItemRow=cr;
407
  // Dòng sản phẩm
408
  for(var i=0;i<qd.items.length;i++){
409
  var it=qd.items[i],row=ws.getRow(cr);
@@ -427,14 +442,14 @@ async function _doExportExcel(d,qd,code,qrUrl){
427
  cr++;
428
  }
429
 
430
- // FIX: THÊM CÁC DÒNG PHÍ (giao hàng, lắp đặt...)
431
  var fees = d.fees || [];
432
  var feeStartRow = cr;
433
  for(var f=0; f<fees.length; f++){
434
  var feeRow = ws.getRow(cr);
435
  feeRow.height=22;
436
  ws.mergeCells(cr, 2, cr, 8);
437
- feeRow.getCell(2).value='⊕ ' + fees[f].label;
438
  feeRow.getCell(2).font={bold:true};
439
  feeRow.getCell(9).value=fees[f].amount;
440
  feeRow.getCell(9).numFmt=MONEY_FMT;
@@ -457,12 +472,25 @@ async function _doExportExcel(d,qd,code,qrUrl){
457
  ws.getCell('I'+cr).numFmt=MONEY_FMT;
458
  ws.getCell('I'+cr).font={bold:true,size:14,color:{argb:'FFF0B840'};};
459
 
460
- // Thông tin cọc nếu có
461
  if(d.deposit>0){
462
  cr++;
463
- ws.mergeCells(cr,1,cr,10);
464
- ws.getCell('A'+cr).value='Cọc: '+fmt(d.deposit)+' | Còn lại: '+fmt(d.remaining);
465
- ws.getCell('A'+cr).font={size:11};
 
 
 
 
 
 
 
 
 
 
 
 
 
466
  }
467
 
468
  wb.calcProperties.fullCalcOnLoad=true;
@@ -555,6 +583,7 @@ window.VAI_QR={
555
  exportDeliveryPDF:_doExportDeliveryPDF,
556
  exportDeliveryExcel:_doExportDeliveryExcel,
557
  fmt:fmt,
 
558
  compactKey:compactKey,
559
  matchItemDiscount:matchItemDiscount,
560
  parseItemDiscountLine:parseItemDiscountLine,
@@ -562,5 +591,5 @@ window.VAI_QR={
562
  setExportButtonState:setExportButtonState,
563
  orderToVAIData:orderToVAIData
564
  };
565
- console.log('[VAI QR v1043 FIX] Loaded - Phí giao hàng, lắp đặt, cọc được thêm vào Excel');
566
  })();
 
34
  function getEffectiveOrderCode(){var n=getCustomerName();if(n)return generateOrderCode(n);var h=window.location.hash;if(h&&h.length>1){var c=h.substring(1);if(/^VAS[A-Z0-9]{3,}$/.test(c))return c;}return generateOrderCode('');}
35
  function getQRUrl(a,c){return'https://img.vietqr.io/image/'+BANK_ID+'-'+BANK_ACCOUNT+'-compact2.png?amount='+(Math.round(a)||0)+'&addInfo='+encodeURIComponent(c||'VAISTUDIO')+'&accountName='+encodeURIComponent(BANK_NAME);}
36
  function fmt(n){if(!n||isNaN(n))return'0đ';return Number(n).toLocaleString('vi-VN')+'đ';}
37
+ function fmtSigned(n){if(!n||isNaN(n))return'0đ';return('+'+(Number(n).toLocaleString('vi-VN')+'đ'));}
38
  function compactKey(s){return stripDiacritics(String(s||'')).toLowerCase().replace(/[^a-z0-9]/g,'');}
39
  function itemKeys(it){var arr=[];['model','sku','code','ma','name'].forEach(function(k){if(it&&it[k])arr.push(compactKey(it[k]));});if(it&&it.name){String(it.name).split('|').forEach(function(x){arr.push(compactKey(x));});}return arr.filter(function(x){return x&&x.length>=3;});}
40
  function matchItemDiscount(it,itemDiscounts){itemDiscounts=itemDiscounts||{};var keys=itemKeys(it);for(var i=0;i<keys.length;i++){var k=keys[i];if(itemDiscounts[k])return itemDiscounts[k];}for(var code in itemDiscounts){for(var j=0;j<keys.length;j++){var kk=keys[j];if(code.length>=3&&kk.length>=3&&(kk.indexOf(code)!==-1||code.indexOf(kk)!==-1))return itemDiscounts[code];}}return 0;}
 
52
 
53
  if(Object.keys(itemDiscounts).length&&line.match(/\\b[A-Za-z]{1,8}[A-Za-z0-9._\-\/]{1,30}\\d[A-Za-z0-9._\-\/]*\\b/i)&&line.match(/\\b(ck|chiết khấu|chiet khau|giảm|giam|discount)\\b/i))return;
54
 
55
+ // CK - FIX: xử lý "Malloca ck 35%" dạng toàn cục
56
  if(line.match(/^(ck|chiết khấu|chiet khau|giảm|giam|discount)/i)){
57
  discount=line;
58
  var ckm=line.match(/([\d.,]+)\\s*(%)?/);
 
62
  }
63
  return;
64
  }
65
+ // FIX: "Tên thương hiệu ck X%" - xử lý global discount sau tên brand
66
+ var brandCkMatch = line.match(/^([A-Za-z]+)\\s*ck\\s*([\\d.,]+)\\s*%/i);
67
+ if(brandCkMatch && !line.match(/\\$/) && !line.match(/%/)){
68
+ var vBrand = parseFloat(brandCkMatch[2].replace(/\\./g,'').replace(',','.'));
69
+ if(vBrand>0 && vBrand<=100) discountPercent=vBrand;
70
+ return;
71
+ }
72
 
73
  // Cọc
74
  if(line.match(/cọc|coc|deposit/i)){
 
83
  return;
84
  }
85
 
86
+ // FIX: "giao thứ X" / "lắp thứ X" = note about delivery day
87
+ if(line.match(/(giao|lap)\\s*thu\\s*\\d/i)){
88
+ var dayMatch = line.match(/(giao|lap)\\s*thu\\s*(\\d+)/i);
89
+ if(dayMatch) {notes.push('Giao thứ ' + dayMatch[2]);}
90
+ return;
91
+ }
92
+
93
  // Phí giao hàng, lắp đặt - FIX QUAN TRỌNG
94
+ var feeMatch=line.match(/([\\d.,]+)\\s*(k|K|nghìn|nghin|triệu|tr|đ|d|vnd)?/);
95
  if(feeMatch){
96
  var amt=parseFloat(feeMatch[1].replace(/\\./g,'').replace(',','.'));
97
  var u=(feeMatch[2]||'').toLowerCase();
 
207
  if(parsed.fees.length){
208
  html+='<div style="padding:8px 12px;background:#fffbeb;border-radius:6px;border:1px solid #fde68a;margin-bottom:8px"><div style="font-weight:700;color:#92400e;font-size:12px;margin-bottom:4px">PHỤ PHÍ</div>';
209
  parsed.fees.forEach(function(f){
210
+ html+='<div style="display:flex;justify-content:space-between;padding:2px 0"><span>+ '+f.label+'</span><span style="font-weight:700">'+fmt(f.amount)+'</span></div>';
211
  });
212
  html+='</div>';
213
  }
 
258
  var feeRows='';
259
  if(d.fees&&d.fees.length){
260
  d.fees.forEach(function(f){
261
+ feeRows+='<tr style="background:#fffbeb"><td colspan="8" style="padding:5px 10px;font-size:11px;color:#92400e">+ '+f.label+'</td><td style="padding:5px 4px;text-align:right;font-size:11px;font-weight:700">'+fmt(f.amount)+'</td></tr>';
262
  });
263
  }
264
  return '<div style="display:flex;align-items:center;gap:10px">'
 
281
  +'<span style="color:#fff;font-weight:800">TỔNG CỘNG</span>'
282
  +'<span style="color:#f0b840;font-weight:900;margin-left:10px">'+fmt(d.grandTotal)+'</span>'
283
  +'</div>'
284
+ +(d.deposit>0?'<div style="margin-top:6px;padding:6px 12px;background:#f0fdf4;font-size:12px"><span>Đặt cọc: <b>'+fmt(d.deposit)+'</b></span><br><span>Còn lại: <b style="color:#dc2626">'+fmt(d.remaining)+'</b></span></div>':'');
285
  }
286
 
287
  function buildDeliveryHTML(qd,code){
 
389
  pdf.save('GH-'+code+'.xlsx');
390
  }
391
 
392
+ // ===== EXPORT EXCEL - FIX BAO GỒM PHÍ, CỌC, CÒN LẠI =====
393
  async function _doExportExcel(d,qd,code,qrUrl){
394
  var MONEY_FMT='#,##0"đ"';
395
  var NUM_FMT='#,##0';
 
398
  ws.views=[{showGridLines:false}];
399
  ws.columns=[{width:5},{width:11},{width:28},{width:13},{width:20},{width:6},{width:13},{width:13},{width:15},{width:14}];
400
 
401
+ ws.mergeCells('A1:J1');
402
+ ws.getCell('A1').value='BẢNG BÁO GIÁ';
403
+ ws.getCell('A1').font={bold:true,size:18,color:{argb:'FFDB9815'}};
404
+ ws.getCell('A1').alignment={horizontal:'center'};
405
 
406
+ ws.getCell('A3').value='Khách hàng:';ws.mergeCells('B3:E3');ws.getCell('B3').value=qd.customer?qd.customer.name:'';
407
+ ws.getCell('H3').value='Mã đơn:';ws.mergeCells('I3:J3');ws.getCell('I3').value=code;
408
+ ws.getCell('A4').value='SĐT:';ws.mergeCells('B4:E4');ws.getCell('B4').value=qd.customer?qd.customer.phone:'';
409
+ ws.getCell('H4').value='Ngày:';ws.mergeCells('I4:J4');ws.getCell('I4').value=qd.customer?qd.customer.date:'';
410
+ ws.getCell('A5').value='Email:';ws.mergeCells('B5:E5');ws.getCell('B5').value=qd.customer?qd.customer.email:'';
411
+ ws.getCell('A6').value='Địa chỉ:';ws.mergeCells('B6:J6');ws.getCell('B6').value=qd.customer?qd.customer.addr:'';
412
 
413
+ var hr=ws.getRow(8);
414
  ['STT','Hình','Tên sản phẩm','Mã SP','Thông tin','SL','Đơn giá','Giá CK','Thành tiền','Ghi chú'].forEach(function(h,i){
415
  var c=hr.getCell(i+1);
416
  c.value=h;
 
418
  c.fill={type:'pattern',pattern:'solid',fgColor:{argb:'FF003F62'};
419
  });
420
 
421
+ var cr=9,firstItemRow=cr;
422
  // Dòng sản phẩm
423
  for(var i=0;i<qd.items.length;i++){
424
  var it=qd.items[i],row=ws.getRow(cr);
 
442
  cr++;
443
  }
444
 
445
+ // FIX: THÊM CÁC DÒNG PHÍ (giao hàng, lắp đặt...) - mỗi phí 1 dòng riêng
446
  var fees = d.fees || [];
447
  var feeStartRow = cr;
448
  for(var f=0; f<fees.length; f++){
449
  var feeRow = ws.getRow(cr);
450
  feeRow.height=22;
451
  ws.mergeCells(cr, 2, cr, 8);
452
+ feeRow.getCell(2).value='+ ' + fees[f].label;
453
  feeRow.getCell(2).font={bold:true};
454
  feeRow.getCell(9).value=fees[f].amount;
455
  feeRow.getCell(9).numFmt=MONEY_FMT;
 
472
  ws.getCell('I'+cr).numFmt=MONEY_FMT;
473
  ws.getCell('I'+cr).font={bold:true,size:14,color:{argb:'FFF0B840'};};
474
 
475
+ // Thông tin cọc - tách thành 2 dòng riêng
476
  if(d.deposit>0){
477
  cr++;
478
+ // Dòng Đặt cọc
479
+ ws.mergeCells(cr,1,cr,8);
480
+ ws.getCell('A'+cr).value='Đặt cọc';
481
+ ws.getCell('A'+cr).font={bold:true,size:11};
482
+ ws.getCell('I'+cr).value=d.deposit;
483
+ ws.getCell('I'+cr).numFmt=MONEY_FMT;
484
+ ws.getCell('I'+cr).font={bold:true};
485
+
486
+ cr++;
487
+ // Dòng Còn lại
488
+ ws.mergeCells(cr,1,cr,8);
489
+ ws.getCell('A'+cr).value='Còn lại';
490
+ ws.getCell('A'+cr).font={bold:true,size:11,color:{argb:'FFDC2626'};};
491
+ ws.getCell('I'+cr).value=d.remaining;
492
+ ws.getCell('I'+cr).numFmt=MONEY_FMT;
493
+ ws.getCell('I'+cr).font={bold:true,color:{argb:'FFDC2626'};};
494
  }
495
 
496
  wb.calcProperties.fullCalcOnLoad=true;
 
583
  exportDeliveryPDF:_doExportDeliveryPDF,
584
  exportDeliveryExcel:_doExportDeliveryExcel,
585
  fmt:fmt,
586
+ fmtSigned:fmtSigned,
587
  compactKey:compactKey,
588
  matchItemDiscount:matchItemDiscount,
589
  parseItemDiscountLine:parseItemDiscountLine,
 
591
  setExportButtonState:setExportButtonState,
592
  orderToVAIData:orderToVAIData
593
  };
594
+ console.log('[VAI QR v1043 FIX] Loaded - Phí giao hàng, lắp đặt, cọc được thêm vào Excel - Format mới: từng dòng phí riêng');
595
  })();