yhart  
                
                  
                    February 6, 2025,  3:49am
                   
                  1 
               
             
            
              Hi all i am from Indonesia.
There has been a recent change in the tax system here where they change the VAT to be 12% from the old 11%.
However essentially is the same 11%, just that value of taxable supply changes.
Old regulation:
New regulation:
Now many of my customers (soon perhaps all) require us to have this value of taxable supply (DPP) amount printed on the invoice.
can we have that in manager??
             
            
              
            
           
          
            
              
                yhart  
              
                  
                    February 6, 2025,  4:04am
                   
                  3 
               
             
            
              oh wow sorry for not looking thorougly, seems like someone brought it up already!
will check on it thanks!
             
            
              
            
           
          
            
              
                yhart  
                
                  
                    February 6, 2025,  4:51am
                   
                  4 
               
             
            
              can you help revise the code and it’s shown like this.
remove Rp. and remove decimal 
location of the DPP should be before the tax? 
 
             
            
              
            
           
          
            
            
              Can you share a screenshot of your Edit Form, I’m a little confused by the invoice you showed.
             
            
              
            
           
          
            
            
              Script Updated to support :
Business data without Base Currency, 
Sales with Withholding Tax, 
Indonesian and English Language, 
en_US and id_ID Number Format, 
 
<script id="script-wrapper">
    document.addEventListener("DOMContentLoaded", processSubtotal);
    function processSubtotal() {
        // Cari semua sel di kolom pertama yang mungkin mengandung "Subtotal" atau "Sub-total"
        const subtotalCell = [...document.querySelectorAll("tbody td:first-child")]
            .find(td => ["subtotal", "sub-total"].includes(td.textContent.trim().toLowerCase()));
        if (!subtotalCell) return;
        // Ambil baris tempat Subtotal ditemukan
        const firstSubtotalRow = subtotalCell.closest("tr");
        const subtotalValueCell = firstSubtotalRow.querySelector("td[data-value]") || firstSubtotalRow.querySelector("td:last-child");
        if (!subtotalValueCell) return;
        // Ambil nilai Subtotal
        const rawValue = subtotalValueCell.dataset.value || subtotalValueCell.textContent.trim();
        const isIdLocale = /,\d{2}$/.test(rawValue);
        const isEnLocale = /\.\d{2}$/.test(rawValue);
        let subtotalValue = isIdLocale 
            ? parseFloat(rawValue.replace(/\./g, "").replace(",", ".")) 
            : parseFloat(rawValue.replace(/,/g, ""));
        if (isNaN(subtotalValue) || subtotalValue === 0) return;
        // Hitung DPP Nilai Lain
        let dppNilaiLain = Math.round((11 / 12) * subtotalValue * 100) / 100;
        // Kloning baris Subtotal dan ubah menjadi DPP Nilai Lain
        const dppRow = firstSubtotalRow.cloneNode(true);
        const dppLabelCell = dppRow.querySelector("td[colspan]") || dppRow.querySelector("td:first-child");
        const dppValueCell = dppRow.querySelector("td[data-value]") || dppRow.querySelector("td:last-child");
        if (!dppLabelCell || !dppValueCell) return;
        dppLabelCell.textContent = "DPP Nilai Lain";
        const includeCurrencySymbol = subtotalValueCell.textContent.trim().includes("Rp");
        // Format angka sesuai locale
        const numberFormatter = new Intl.NumberFormat(isIdLocale ? "id-ID" : "en-US", {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2
        });
        dppValueCell.textContent = includeCurrencySymbol
            ? `Rp ${numberFormatter.format(dppNilaiLain)}`
            : numberFormatter.format(dppNilaiLain);
        dppValueCell.setAttribute("data-value", dppNilaiLain.toFixed(2).replace(".", isIdLocale ? "," : "."));
        // Sisipkan baris setelah Subtotal pertama
        firstSubtotalRow.insertAdjacentElement("afterend", dppRow);
        // Hapus script setelah eksekusi
        document.getElementById("script-wrapper")?.remove();
    }
</script>
Script optimization as suggested by @eko . Thanks for the advice! 
             
            
              5 Likes 
            
            
           
          
            
              
                yhart  
                
                  
                    February 6, 2025, 11:24am
                   
                  9 
               
             
            
              Perfect!! i tried it and still got the decimals going, then i set the min and max fraction from 2 to 0. and its perfect.
thanks so much!
             
            
              
            
           
          
          
            
              
                eko  
              
                  
                    February 6, 2025, 12:02pm
                   
                  11 
               
             
            
              
@Mabaega  maybe consider changing that part of the code to:
// Format angka sesuai locale
const numberFormatter = new Intl.NumberFormat(isIdLocale ? "id-ID" : "en-US", {
    minimumFractionDigits: isIdLocale ? 0 : 2,
    maximumFractionDigits: isIdLocale ? 0 : 2
});
Thus for Indonesia (id-ID), we set both minimumFractionDigits and maximumFractionDigits to 0, thus no decimal places will be shown, and for the US (en-US), we keep minimumFractionDigits and maximumFractionDigits set to 2, ensuring that 2 decimal places are always shown.
             
            
              1 Like 
            
            
           
          
            
              
                yhart  
              
                  
                    February 7, 2025,  4:07am
                   
                  12 
               
             
            
              Thanks for the update both of you! @eko  @Mabaega  you guys are awesome!
             
            
              
            
           
          
            
              
                yhart  
                
                  
                    February 7, 2025,  4:36am
                   
                  13 
               
             
            
              By the way i tried changing this code. but then it’s still reverting back to 2 digits.
i may not understand completely what is this id-ID and en-US means? is this related to the language of manager it’s shown as?
             
            
              
            
           
          
            
              
                Mabaega  
              
                  
                    February 7, 2025,  5:20am
                   
                  14 
               
             
            
              @yhart 
I don’t understand why you choose to use numbers without decimals on your invoices.  As far as I know, in the CoreTax  system all numbers use two Decimal Places.
For your needs, you can change this section, replacing 2 with 0.
// Format angka sesuai locale
        const numberFormatter = new Intl.NumberFormat(isIdLocale ? "id-ID" : "en-US", {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2
        });
to
// Format angka sesuai locale
        const numberFormatter = new Intl.NumberFormat(isIdLocale ? "id-ID" : "en-US", {
            minimumFractionDigits: 0,
            maximumFractionDigits: 0
        });
 
            
              
            
           
          
            
              
                eko  
              
                  
                    February 7, 2025,  6:15am
                   
                  15 
               
             
            
              
id-ID stand for Indonesian language and country code, respectively. en-US for English and United States. These codes are used in internationalization (i18n) functions like Intl.NumberFormat() to apply locale-specific formatting rules, such as number formatting, currency symbols, and date/time formats.
             
            
              
            
           
          
            
              
                yhart  
              
                  
                    February 7, 2025,  8:04am
                   
                  16 
               
             
            
              my customer’s requirements invoices to be without decimals.
             
            
              
            
           
          
            
              
                yhart  
              
                  
                    August 14, 2025,  3:49am
                   
                  17 
               
             
            
              @mabaega  I have sinced updated to 25.8 version and my footers doesnt work anymore (both retention field and DPPBL). is there some changes in the code to be done?
             
            
              
            
           
          
            
            
              You can try using a custom theme and moving the footer script to that theme.
This should work.
             
            
              
            
           
          
            
              
                yhart  
              
                  
                    August 14, 2025,  7:08am
                   
                  19 
               
             
            
              Below is the code, i copied all directly but doesnt work. The invoice just goes blank. where does it need modification?
%%Retention (%)%%
             
            
              
            
           
          
            
              
                yhart  
              
                  
                    August 14, 2025,  7:11am
                   
                  22 
               
             
            
              %%Retention (%)%%
document.addEventListener("DOMContentLoaded", processSubtotal);
function processSubtotal() {
    // Locate "Sub-Total" row to fetch Retention percentage base
    const subTotalCell = [...document.querySelectorAll("tbody td:first-child")]
        .find(td => td.textContent.trim().toLowerCase() === "sub-total");
    if (!subTotalCell) return;
    const subTotalRow = subTotalCell.closest("tr");
    const subTotalValueCell = subTotalRow.querySelector("td[data-value]") || subTotalRow.querySelector("td:last-child");
    if (!subTotalValueCell) return;
    const rawValue = subTotalValueCell.dataset.value || subTotalValueCell.textContent.trim();
    const isIdLocale = /,\d{2}$/.test(rawValue);
    let subTotalValue = isIdLocale 
        ? parseFloat(rawValue.replace(/\./g, "").replace(",", ".")) 
        : parseFloat(rawValue.replace(/,/g, ""));
    if (isNaN(subTotalValue) || subTotalValue === 0) return;
    // Fetch Retention Percentage from UI Element
    let retentionText = document.getElementById("retention-value")?.textContent.trim();
    let retentionPercentage = parseFloat(retentionText.replace(/[^\d.]/g, "")); // Extract only numbers
    if (isNaN(retentionPercentage) || retentionPercentage < 0 || retentionPercentage > 100) {
        retentionPercentage = 10; // Default to 10% if invalid
    }
    // Compute Retention
    let Retention = Math.round(subTotalValue * (retentionPercentage / 100));
    // Locate "Total" row for Balance Due calculation
    const totalCell = [...document.querySelectorAll("tbody td:first-child")]
        .find(td => td.textContent.trim().toLowerCase() === "total");
    if (!totalCell) return;
    const totalRow = totalCell.closest("tr");
    const totalValueCell = totalRow.querySelector("td[data-value]") || totalRow.querySelector("td:last-child");
    if (!totalValueCell) return;
    // Extract and parse Total value
    const rawTotalValue = totalValueCell.dataset.value || totalValueCell.textContent.trim();
    let totalValue = isIdLocale 
        ? parseFloat(rawTotalValue.replace(/\./g, "").replace(",", ".")) 
        : parseFloat(rawTotalValue.replace(/,/g, ""));
    if (isNaN(totalValue)) return;
    // Compute Balance Due using Total
    let BalanceDue = totalValue - Retention; // ✅ Correct formula
    // Format numbers
    const numberFormatter = new Intl.NumberFormat(isIdLocale ? "id-ID" : "en-US", {
        minimumFractionDigits: 0,
        maximumFractionDigits: 0
    });
    const includeCurrencySymbol = totalValueCell.textContent.trim().includes("Rp");
    function createRow(label, value) {
        const newRow = totalRow.cloneNode(true);
        const labelCell = newRow.querySelector("td[colspan]") || newRow.querySelector("td:first-child");
        const valueCell = newRow.querySelector("td[data-value]") || newRow.querySelector("td:last-child");
        if (!labelCell || !valueCell) return null;
        labelCell.textContent = label;
        valueCell.textContent = includeCurrencySymbol 
            ? `Rp ${numberFormatter.format(value)}` 
            : numberFormatter.format(value);
        valueCell.setAttribute("data-value", value.toFixed(2).replace(".", isIdLocale ? "," : "."));
        
        return newRow;
    }
    const retRow = createRow(`Retention (${retentionPercentage}%)`, Retention);
    const baldueRow = createRow("Balance Due", BalanceDue); // ✅ Now correctly using Total - Retention
    if (retRow && baldueRow) {
        totalRow.insertAdjacentElement("afterend", retRow);
        retRow.insertAdjacentElement("afterend", baldueRow);
    }
    document.getElementById("script-wrapper")?.remove();
}