Esketit - Add Net Return and Colorize Fields

Adds Net Return to the statement and colorizes contributing fields.

Tendrás que instalar una extensión para tu navegador como Tampermonkey, Greasemonkey o Violentmonkey si quieres utilizar este script.

You will need to install an extension such as Tampermonkey to install this script.

Necesitarás instalar una extensión como Tampermonkey o Violentmonkey para instalar este script.

Necesitarás instalar una extensión como Tampermonkey o Userscripts para instalar este script.

Necesitará instalar una extensión como Tampermonkey para instalar este script.

Necesitarás instalar una extensión para administrar scripts de usuario si quieres instalar este script.

(Ya tengo un administrador de scripts de usuario, déjame instalarlo)

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión como Stylus para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

Necesitará instalar una extensión del gestor de estilos de usuario para instalar este estilo.

(Ya tengo un administrador de estilos de usuario, déjame instalarlo)

// ==UserScript==
// @name         Esketit - Add Net Return and Colorize Fields
// @namespace    http://esketit.com/
// @version      20250729
// @description  Adds Net Return to the statement and colorizes contributing fields.
// @author       rs232
// @match        https://*esketit.com/investor/account-statement
// @icon         https://www.google.com/s2/favicons?sz=32&domain_url=https%3A%2F%2Fwww.esketit.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // Define the colors for easy modification
    const DARK_GREEN = "#2E8B57";
    const PALE_GREEN = "#F0FFF0";

    // Define amber colors as requested
    const LIGHTER_AMBER_BACKGROUND = "#FFF8E1"; // A very light, almost cream amber
    const DARKER_AMBER_TEXT = "#E65100";      // A darker, more orange-brown amber

    // Helper function to parse currency strings.
    function parseCurrency(value) {
        if (!value) return 0;
        return parseFloat(value.replace('€', '').trim().replace(/\s/g, '').replace(',', '.')) || 0;
    }

    // Helper function to find a table row by its first cell's text.
    function findRowByLabel(label) {
        const rows = document.querySelectorAll('tr');
        for (const row of rows) {
            const firstCell = row.querySelector('td:first-child');
            if (firstCell && firstCell.textContent.trim() === label) {
                return row;
            }
        }
        return null;
    }

    // Function to apply colors to summary rows based on their value.
    function colorizeSummaryRows() {
        const rowsToColorize = {
            green: ["Interest received", "Bonus received", "Referral bonus received", "Secondary market income"],
            red: ["Secondary market expense"],
            amber: ["Sold on secondary market"]
        };

        // Handle green rows
        rowsToColorize.green.forEach(label => {
            const row = findRowByLabel(label);
            if (row) {
                const valueCell = row.querySelector('td:nth-child(2)');
                const labelCell = row.querySelector('td:first-child');
                const value = valueCell ? parseCurrency(valueCell.textContent) : 0;

                if (value > 0) {
                    labelCell.style.color = DARK_GREEN;
                    valueCell.style.color = DARK_GREEN;
                    row.style.backgroundColor = PALE_GREEN;
                } else {
                    labelCell.style.color = "";
                    valueCell.style.color = "";
                    row.style.backgroundColor = "";
                }
            }
        });

        // Handle red rows
        rowsToColorize.red.forEach(label => {
            const row = findRowByLabel(label);
            if (row) {
                const valueCell = row.querySelector('td:nth-child(2)');
                const labelCell = row.querySelector('td:first-child');
                const value = valueCell ? parseCurrency(valueCell.textContent) : 0;

                if (value < 0) {
                    labelCell.style.color = '#FA5053';
                    valueCell.style.color = '#FA5053';
                    row.style.backgroundColor = "#FFeeea"; // pale red
                } else {
                    labelCell.style.color = "";
                    valueCell.style.color = "";
                    row.style.backgroundColor = "";
                }
            }
        });

        // Handle amber rows with the new lighter background and darker text
        rowsToColorize.amber.forEach(label => {
            const row = findRowByLabel(label);
            if (row) {
                const valueCell = row.querySelector('td:nth-child(2)');
                const labelCell = row.querySelector('td:first-child');
                const value = valueCell ? parseCurrency(valueCell.textContent) : 0;

                if (value > 0) {
                    labelCell.style.color = DARKER_AMBER_TEXT;       // Darker amber text
                    valueCell.style.color = DARKER_AMBER_TEXT;       // Darker amber text
                    row.style.backgroundColor = LIGHTER_AMBER_BACKGROUND; // Lighter amber background
                } else {
                    labelCell.style.color = "";
                    valueCell.style.color = "";
                    row.style.backgroundColor = "";
                }
            }
        });
    }

    // This function will be called periodically to recalculate and update the UI.
    function updateNetReturn() {
        const closingBalanceRow = findRowByLabel("Closing balance");
        const interestReceivedRow = findRowByLabel("Interest received");

        if (closingBalanceRow && interestReceivedRow) {
            const interestValueCell = interestReceivedRow.querySelector('td:nth-child(2)');
            const interestValue = interestValueCell ? parseCurrency(interestValueCell.textContent) : 0;

            if (interestValue !== 0 || findRowByLabel("Secondary market expense")?.querySelector('td:nth-child(2)')?.textContent.trim() !== '€0,00') {
                 let netReturnTotal = 0;
                 const labelsForNetReturn = [
                     "Interest received",
                     "Bonus received",
                     "Referral bonus received",
                     "Secondary market income",
                     "Secondary market expense"
                 ];

                 labelsForNetReturn.forEach(label => {
                     const row = findRowByLabel(label);
                     if (row) {
                         const valueCell = row.querySelector('td:nth-child(2)');
                         if (valueCell) {
                             netReturnTotal += parseCurrency(valueCell.textContent);
                         }
                     }
                 });

                 const formattedNetReturn = `€${netReturnTotal.toFixed(2).replace('.', ',').replace(/\B(?=(\d{3})+(?!\d))/g, '\u00A0')}`;
                 let netReturnRow = document.getElementById('net-return-row');

                 const exampleRow = findRowByLabel("Opening balance");
                 const exampleLabelCell = exampleRow ? exampleRow.querySelector('td:first-child') : null;
                 const exampleValueCell = exampleRow ? exampleRow.querySelector('td:nth-child(2)') : null;

                 if (!netReturnRow) {
                     netReturnRow = document.createElement('tr');
                     netReturnRow.id = 'net-return-row';

                     if (exampleRow && exampleRow.hasAttribute('data-v-344f568a')) {
                         netReturnRow.setAttribute('data-v-344f568a', exampleRow.getAttribute('data-v-344f568a'));
                     }

                     const labelCell = exampleLabelCell ? exampleLabelCell.cloneNode(false) : document.createElement('td');
                     const valueCell = exampleValueCell ? exampleValueCell.cloneNode(false) : document.createElement('td');

                     labelCell.textContent = 'Net return';
                     labelCell.style.fontWeight = 'bold';
                     labelCell.style.color = '#ffffff'; // Swapped text color

                     valueCell.textContent = formattedNetReturn;
                     valueCell.style.fontWeight = 'bold';
                     valueCell.style.color = PALE_GREEN; // Swapped text color
                     valueCell.style.textAlign = 'right';

                     netReturnRow.appendChild(labelCell);
                     netReturnRow.appendChild(valueCell);

                     closingBalanceRow.parentNode.insertBefore(netReturnRow, closingBalanceRow.nextSibling);
                 } else {
                     const valueCell = netReturnRow.querySelector('td:nth-child(2)');
                     if (valueCell) {
                         valueCell.textContent = formattedNetReturn;
                         valueCell.style.fontWeight = 'bold';
                         valueCell.style.color = PALE_GREEN; // Swapped text color
                         valueCell.style.textAlign = 'right';
                     }
                     const labelCell = netReturnRow.querySelector('td:first-child');
                     if (labelCell) {
                         labelCell.style.fontWeight = 'bold';
                         labelCell.style.color = PALE_GREEN; // Swapped text color
                     }
                 }
                 netReturnRow.style.backgroundColor = DARK_GREEN; // Swapped background color

                 colorizeSummaryRows();
            }
        }
    }

    // Set up a continuous polling loop to update the Net Return and colors.
    setInterval(updateNetReturn, 500);

})();