| @@ -365,11 +365,15 @@ | ||
| 365 | 365 | } else { |
| 366 | 366 | // Fallback to hardcoded calculation |
| 367 | 367 | var quantity = parseFloat($item.find('input[name*="[quantity]"]').val()) || 0; |
| 368 | 368 | var price = parseFloat($item.find('input[name*="[price]"]').val()) || 0; |
| 369 | - var adjustPercentage = parseFloat($item.find('input[name*="[adjust_percentage]"]').val()) || 0; | |
| 369 | + var adjustPercentage = 0; | |
| 370 | + // Only apply adjust percentage if the adjust field is enabled | |
| 371 | + if (window.easyInvoice && window.easyInvoice.showAdjustField) { | |
| 372 | + adjustPercentage = parseFloat($item.find('input[name*="[adjust_percentage]"]').val()) || 0; | |
| 373 | + } | |
| 370 | 374 | var baseTotal = quantity * price; |
| 371 | - var total = baseTotal * (1 + adjustPercentage / 100); | |
| 375 | + var total = easyInvoiceRoundMoney(baseTotal * (1 + adjustPercentage / 100)); | |
| 372 | 376 | |
| 373 | 377 | // Update the total field |
| 374 | 378 | var $totalField = $item.find('input[name*="[total]"]'); |
| 375 | 379 | $totalField.val(total.toFixed(2)); |
| @@ -397,11 +401,15 @@ | ||
| 397 | 401 | } else { |
| 398 | 402 | // Fallback to hardcoded summary |
| 399 | 403 | var quantity = parseFloat($item.find('input[name*="[quantity]"]').val()) || 0; |
| 400 | 404 | var price = parseFloat($item.find('input[name*="[price]"]').val()) || 0; |
| 401 | - var adjustPercentage = parseFloat($item.find('input[name*="[adjust_percentage]"]').val()) || 0; | |
| 405 | + var adjustPercentage = 0; | |
| 406 | + // Only apply adjust percentage if the adjust field is enabled | |
| 407 | + if (window.easyInvoice && window.easyInvoice.showAdjustField) { | |
| 408 | + adjustPercentage = parseFloat($item.find('input[name*="[adjust_percentage]"]').val()) || 0; | |
| 409 | + } | |
| 402 | 410 | var baseTotal = quantity * price; |
| 403 | - var total = baseTotal * (1 + adjustPercentage / 100); | |
| 411 | + var total = easyInvoiceRoundMoney(baseTotal * (1 + adjustPercentage / 100)); | |
| 404 | 412 | |
| 405 | 413 | $item.find('.quantity-summary').text(quantity); |
| 406 | 414 | $item.find('.price-summary').text(price.toFixed(2)); |
| 407 | 415 | $item.find('.total-summary').text(total.toFixed(2)); |
| @@ -551,9 +559,9 @@ | ||
| 551 | 559 | // Update client info fields |
| 552 | 560 | $('#client_name_display').text(client.name || ''); |
| 553 | 561 | $('#client_email_display').text(client.email || ''); |
| 554 | 562 | $('#client_phone_display').text(client.phone || ''); |
| 555 | - $('#client_address_display').html((client.address || '').replace(/\n/g, '<br>')); | |
| 563 | + $('#client_address_display').html(easyInvoiceAddressHtml(client.address)); | |
| 556 | 564 | |
| 557 | 565 | // Show client info section |
| 558 | 566 | $('#client_info').show(); |
| 559 | 567 | return; |
| @@ -575,9 +583,9 @@ | ||
| 575 | 583 | // Update client info fields |
| 576 | 584 | $('#client_name_display').text(client.name); |
| 577 | 585 | $('#client_email_display').text(client.email); |
| 578 | 586 | $('#client_phone_display').text(client.phone || ''); |
| 579 | - $('#client_address_display').html(client.address.replace(/\n/g, '<br>') || ''); | |
| 587 | + $('#client_address_display').html(easyInvoiceAddressHtml(client.address)); | |
| 580 | 588 | |
| 581 | 589 | // Show client info section |
| 582 | 590 | $('#client_info').show(); |
| 583 | 591 | } else { |
| @@ -1054,9 +1062,9 @@ | ||
| 1054 | 1062 | // Set client info if available |
| 1055 | 1063 | if (easyInvoice.clientData) { |
| 1056 | 1064 | $('#client_name_display').text(easyInvoice.clientData.name || ''); |
| 1057 | 1065 | $('#client_email_display').text(easyInvoice.clientData.email || ''); |
| 1058 | - $('#client_address_display').html((easyInvoice.clientData.address || '').replace(/\n/g, '<br>')); | |
| 1066 | + $('#client_address_display').html(easyInvoiceAddressHtml(easyInvoice.clientData.address)); | |
| 1059 | 1067 | $('#client_info').show(); |
| 1060 | 1068 | } |
| 1061 | 1069 | |
| 1062 | 1070 | // Set items |
| @@ -1247,9 +1255,13 @@ | ||
| 1247 | 1255 | calculateFieldValue: function(fieldName, $item) { |
| 1248 | 1256 | if (fieldName === 'total') { |
| 1249 | 1257 | var quantity = parseFloat(this.getFieldValue('quantity', $item)) || 0; |
| 1250 | 1258 | var price = parseFloat(this.getFieldValue('price', $item)) || 0; |
| 1251 | - var adjustPercentage = parseFloat(this.getFieldValue('adjust_percentage', $item)) || 0; | |
| 1259 | + var adjustPercentage = 0; | |
| 1260 | + // Only apply adjust percentage if the adjust field is enabled | |
| 1261 | + if (window.easyInvoice && window.easyInvoice.showAdjustField) { | |
| 1262 | + adjustPercentage = parseFloat(this.getFieldValue('adjust_percentage', $item)) || 0; | |
| 1263 | + } | |
| 1252 | 1264 | var baseTotal = quantity * price; |
| 1253 | 1265 | var total = baseTotal * (1 + adjustPercentage / 100); |
| 1254 | 1266 | return total; |
| 1255 | 1267 | } |
| @@ -1371,10 +1383,22 @@ | ||
| 1371 | 1383 | this.setupClientSelection(); |
| 1372 | 1384 | } |
| 1373 | 1385 | }; |
| 1374 | 1386 | |
| 1387 | +// Address text -> HTML with line breaks, escaped: the address is what the | |
| 1388 | +// client typed into their portal profile, so it must never reach .html() raw. | |
| 1389 | +// Half-up rounding to cents, matching PHP round($x, 2) (7 x 1.005 is 7.04, not | |
| 1390 | +// the 7.03 that toFixed() gives from binary floats). | |
| 1391 | +function easyInvoiceRoundMoney(v) { | |
| 1392 | + return Number(Math.round(Number((parseFloat(v) || 0) + 'e2')) + 'e-2'); | |
| 1393 | +} | |
| 1394 | + | |
| 1395 | +function easyInvoiceAddressHtml(address) { | |
| 1396 | + return jQuery('<div>').text(address || '').html().replace(/\n/g, '<br>'); | |
| 1397 | +} | |
| 1398 | + | |
| 1375 | 1399 | // Initialize invoice builder when document is ready |
| 1376 | - jQuery(document).ready(function($) { | |
| 1400 | +jQuery(document).ready(function($) { | |
| 1377 | 1401 | // Initialize the invoice builder |
| 1378 | 1402 | if (typeof EasyInvoiceBuilder !== 'undefined') { |
| 1379 | 1403 | EasyInvoiceBuilder.init(); |
| 1380 | 1404 | } |