Upload qr-payment-v1043-FIXED.js
Browse files- 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">
|
| 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>
|
| 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('
|
| 387 |
-
ws.getCell('
|
| 388 |
-
ws.getCell('
|
| 389 |
-
ws.getCell('
|
| 390 |
|
| 391 |
-
ws.getCell('
|
| 392 |
-
ws.getCell('
|
| 393 |
-
ws.getCell('
|
| 394 |
-
ws.getCell('
|
| 395 |
-
ws.getCell('
|
| 396 |
-
ws.getCell('
|
| 397 |
|
| 398 |
-
var hr=ws.getRow(
|
| 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=
|
| 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='
|
| 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
|
| 461 |
if(d.deposit>0){
|
| 462 |
cr++;
|
| 463 |
-
|
| 464 |
-
ws.
|
| 465 |
-
ws.getCell('A'+cr).
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 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 |
})();
|