
Runner.pages.PageSettings.addPageEvent( 
	"supplier_bill", 
	"add", 
	"afterPageReady", 
	function(pageObj, proxy, pageid, inlineRow, inlineObject, row ) {
		/* ============================================================
   BuildLedger Finance
   Supplier Bill - Live Detail + Header Summary Preview
   Works for both saved rows and inline add/edit rows.

   Put in:
   supplier_bill → Add page  → JavaScript OnLoad event
   supplier_bill → Edit page → JavaScript OnLoad event
   ============================================================ */

(function () {

    $("#bl_supplier_bill_live_summary").remove();

    function toNumber(value) {
        if (value === null || value === undefined) {
            return 0;
        }

        value = String(value).replace(/,/g, "").trim();

        if (value === "") {
            return 0;
        }

        var num = parseFloat(value);

        if (isNaN(num)) {
            return 0;
        }

        return num;
    }

    function round4(value) {
        return Math.round((toNumber(value) + Number.EPSILON) * 10000) / 10000;
    }

    function raw4(value) {
        return round4(value).toFixed(4);
    }

    function money(value) {
        return round4(value).toLocaleString("en-US", {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2
        });
    }

    function normalizeText(value) {
        return String(value || "")
            .toLowerCase()
            .replace(/[^a-z0-9]+/g, "");
    }

    function findControl($scope, fieldName) {
        return $scope.find(
            "input[name^='value_" + fieldName + "'], " +
            "select[name^='value_" + fieldName + "'], " +
            "textarea[name^='value_" + fieldName + "'], " +
            "input[id^='value_" + fieldName + "'], " +
            "select[id^='value_" + fieldName + "'], " +
            "textarea[id^='value_" + fieldName + "']"
        ).first();
    }

    function getControlValue($row, fieldName) {
        var $ctrl = findControl($row, fieldName);

        if ($ctrl.length) {
            return $ctrl.val();
        }

        return "";
    }

    function getCellText($row, colIndex) {
        if (colIndex === undefined || colIndex === null || colIndex < 0) {
            return "";
        }

        var $cell = $row.children("td").eq(colIndex);

        if (!$cell.length) {
            return "";
        }

        return $.trim($cell.text());
    }

    function getRowValue($row, fieldName, colIndex) {
        var controlValue = getControlValue($row, fieldName);

        if (controlValue !== "") {
            return controlValue;
        }

        return getCellText($row, colIndex);
    }

    function setRowValue($row, fieldName, colIndex, value) {
        var rawValue = raw4(value);
        var moneyValue = money(value);

        var $ctrl = findControl($row, fieldName);

        if ($ctrl.length) {
            $ctrl.val(rawValue);
            return;
        }

        if (colIndex !== undefined && colIndex !== null && colIndex >= 0) {
            var $cell = $row.children("td").eq(colIndex);

            if ($cell.length && !$cell.find("input, select, textarea").length) {
                $cell.text(moneyValue);
            }
        }
    }

    function parseRateFromText(value) {
        value = String(value || "");

        var match = value.match(/(\d+(\.\d+)?)/);

        if (match) {
            return toNumber(match[1]);
        }

        return 0;
    }

    function parseRateFromSelectedText($row, fieldName) {
        var $ctrl = findControl($row, fieldName);

        if (!$ctrl.length || !$ctrl.is("select")) {
            return 0;
        }

        return parseRateFromText($ctrl.find("option:selected").text());
    }

    function setHeaderField(fieldName, value) {
        var rawValue = raw4(value);
        var moneyValue = money(value);

        $(
            "input[name^='value_" + fieldName + "'], " +
            "input[id^='value_" + fieldName + "'], " +
            "textarea[name^='value_" + fieldName + "'], " +
            "textarea[id^='value_" + fieldName + "']"
        ).each(function () {
            $(this).val(rawValue);
        });

        $(
            "[id^='display_value_" + fieldName + "'], " +
            "[id^='readonly_value_" + fieldName + "'], " +
            "span[id^='value_" + fieldName + "'], " +
            "div[id^='value_" + fieldName + "']"
        ).each(function () {
            var $el = $(this);

            if ($el.is("input, textarea, select")) {
                $el.val(rawValue);
            } else {
                $el.text(moneyValue);
            }
        });
    }

    function getDetailColumnMap($table) {
        var map = {};
        var foundHeader = false;

        $table.find("tr").each(function () {
            var $row = $(this);
            var rowText = normalizeText($row.text());

            if (
                rowText.indexOf("quantity") < 0 ||
                rowText.indexOf("unitprice") < 0 ||
                rowText.indexOf("linetotal") < 0
            ) {
                return true;
            }

            $row.children("th,td").each(function (index) {
                var text = normalizeText($(this).text());

                if (text === "quantity") {
                    map.quantity = index;
                } else if (text === "unitprice") {
                    map.unit_price = index;
                } else if (text === "grossamount") {
                    map.gross_amount = index;
                } else if (text === "discount" || text === "discountamount") {
                    map.discount_amount = index;
                } else if (text === "netbeforetax") {
                    map.net_before_tax = index;
                } else if (text === "vatcode") {
                    map.vat_tax_code_id = index;
                } else if (text === "vatrate" || text === "vatratepercent") {
                    map.vat_rate_percent = index;
                } else if (text === "inputvat") {
                    map.input_vat_amount = index;
                } else if (text === "withholdingtaxcode") {
                    map.withholding_tax_code_id = index;
                } else if (text === "withholding") {
                    map.withholding_amount = index;
                } else if (text === "linetotal") {
                    map.line_total_amount = index;
                }
            });

            foundHeader = true;
            return false;
        });

        if (!foundHeader) {
            return null;
        }

        if (
            map.quantity === undefined ||
            map.unit_price === undefined ||
            map.line_total_amount === undefined
        ) {
            return null;
        }

        return map;
    }

    function recalcSupplierBill() {
        var subtotal = 0;
        var discountTotal = 0;
        var inputVatTotal = 0;
        var withholdingTotal = 0;
        var grandTotal = 0;

        $("table:visible").each(function () {
            var $table = $(this);
            var col = getDetailColumnMap($table);

            if (!col) {
                return true;
            }

            $table.find("tr").each(function () {
                var $row = $(this);

                if ($row.children("th").length > 0) {
                    return true;
                }

                var rowText = normalizeText($row.text());

                if (
                    rowText.indexOf("quantity") >= 0 &&
                    rowText.indexOf("unitprice") >= 0 &&
                    rowText.indexOf("linetotal") >= 0
                ) {
                    return true;
                }

                var qty = toNumber(getRowValue($row, "quantity", col.quantity));
                var unitPrice = toNumber(getRowValue($row, "unit_price", col.unit_price));

                var existingGross = toNumber(getRowValue($row, "gross_amount", col.gross_amount));
                var existingLineTotal = toNumber(getRowValue($row, "line_total_amount", col.line_total_amount));

                if (qty <= 0 && unitPrice <= 0 && existingGross <= 0 && existingLineTotal <= 0) {
                    return true;
                }

                var discountAmount = toNumber(getRowValue($row, "discount_amount", col.discount_amount));

                var vatRate = toNumber(getRowValue($row, "vat_rate_percent", col.vat_rate_percent));

                if (vatRate <= 0) {
                    vatRate = parseRateFromSelectedText($row, "vat_tax_code_id");
                }

                if (vatRate <= 0) {
                    vatRate = parseRateFromText(getRowValue($row, "vat_tax_code_id", col.vat_tax_code_id));
                }

                var withholdingRate = toNumber(getControlValue($row, "withholding_rate_percent"));

                if (withholdingRate <= 0) {
                    withholdingRate = parseRateFromSelectedText($row, "withholding_tax_code_id");
                }

                if (withholdingRate <= 0) {
                    withholdingRate = parseRateFromText(getRowValue($row, "withholding_tax_code_id", col.withholding_tax_code_id));
                }

                var grossAmount = round4(qty * unitPrice);

                if (grossAmount <= 0 && existingGross > 0) {
                    grossAmount = existingGross;
                }

                var netBeforeTax = round4(grossAmount - discountAmount);

                if (netBeforeTax < 0) {
                    netBeforeTax = 0;
                }

                var inputVatAmount = round4(netBeforeTax * (vatRate / 100));
                var withholdingAmount = round4(netBeforeTax * (withholdingRate / 100));
                var lineTotalAmount = round4(netBeforeTax + inputVatAmount - withholdingAmount);

                setRowValue($row, "gross_amount", col.gross_amount, grossAmount);
                setRowValue($row, "discount_amount", col.discount_amount, discountAmount);
                setRowValue($row, "net_before_tax", col.net_before_tax, netBeforeTax);
                setRowValue($row, "vat_rate_percent", col.vat_rate_percent, vatRate);
                setRowValue($row, "input_vat_amount", col.input_vat_amount, inputVatAmount);
                setRowValue($row, "withholding_amount", col.withholding_amount, withholdingAmount);
                setRowValue($row, "line_total_amount", col.line_total_amount, lineTotalAmount);

                subtotal += grossAmount;
                discountTotal += discountAmount;
                inputVatTotal += inputVatAmount;
                withholdingTotal += withholdingAmount;
                grandTotal += lineTotalAmount;
            });
        });

        setHeaderField("subtotal_amount", subtotal);
        setHeaderField("discount_amount", discountTotal);
        setHeaderField("input_vat_amount", inputVatTotal);
        setHeaderField("withholding_amount", withholdingTotal);
        setHeaderField("grand_total_amount", grandTotal);
        setHeaderField("base_grand_total_amount", grandTotal);
    }

    function delayedRecalc() {
        setTimeout(recalcSupplierBill, 100);
        setTimeout(recalcSupplierBill, 300);
        setTimeout(recalcSupplierBill, 700);
    }

    $(document).on("keyup input change", "input, select, textarea", function () {
        delayedRecalc();
    });

    $(document).on("click", "a, button, input[type='button'], input[type='submit']", function () {
        delayedRecalc();
    });

    delayedRecalc();

})();
});


Runner.pages.PageSettings.addPageEvent( 
	"supplier_bill", 
	"edit", 
	"afterPageReady", 
	function(pageObj, proxy, pageid, inlineRow, inlineObject, row ) {
		/* ============================================================
   BuildLedger Finance
   Supplier Bill - Live Detail + Header Summary Preview
   Works for both saved rows and inline add/edit rows.

   Put in:
   supplier_bill → Add page  → JavaScript OnLoad event
   supplier_bill → Edit page → JavaScript OnLoad event
   ============================================================ */

(function () {

    $("#bl_supplier_bill_live_summary").remove();

    function toNumber(value) {
        if (value === null || value === undefined) {
            return 0;
        }

        value = String(value).replace(/,/g, "").trim();

        if (value === "") {
            return 0;
        }

        var num = parseFloat(value);

        if (isNaN(num)) {
            return 0;
        }

        return num;
    }

    function round4(value) {
        return Math.round((toNumber(value) + Number.EPSILON) * 10000) / 10000;
    }

    function raw4(value) {
        return round4(value).toFixed(4);
    }

    function money(value) {
        return round4(value).toLocaleString("en-US", {
            minimumFractionDigits: 2,
            maximumFractionDigits: 2
        });
    }

    function normalizeText(value) {
        return String(value || "")
            .toLowerCase()
            .replace(/[^a-z0-9]+/g, "");
    }

    function findControl($scope, fieldName) {
        return $scope.find(
            "input[name^='value_" + fieldName + "'], " +
            "select[name^='value_" + fieldName + "'], " +
            "textarea[name^='value_" + fieldName + "'], " +
            "input[id^='value_" + fieldName + "'], " +
            "select[id^='value_" + fieldName + "'], " +
            "textarea[id^='value_" + fieldName + "']"
        ).first();
    }

    function getControlValue($row, fieldName) {
        var $ctrl = findControl($row, fieldName);

        if ($ctrl.length) {
            return $ctrl.val();
        }

        return "";
    }

    function getCellText($row, colIndex) {
        if (colIndex === undefined || colIndex === null || colIndex < 0) {
            return "";
        }

        var $cell = $row.children("td").eq(colIndex);

        if (!$cell.length) {
            return "";
        }

        return $.trim($cell.text());
    }

    function getRowValue($row, fieldName, colIndex) {
        var controlValue = getControlValue($row, fieldName);

        if (controlValue !== "") {
            return controlValue;
        }

        return getCellText($row, colIndex);
    }

    function setRowValue($row, fieldName, colIndex, value) {
        var rawValue = raw4(value);
        var moneyValue = money(value);

        var $ctrl = findControl($row, fieldName);

        if ($ctrl.length) {
            $ctrl.val(rawValue);
            return;
        }

        if (colIndex !== undefined && colIndex !== null && colIndex >= 0) {
            var $cell = $row.children("td").eq(colIndex);

            if ($cell.length && !$cell.find("input, select, textarea").length) {
                $cell.text(moneyValue);
            }
        }
    }

    function parseRateFromText(value) {
        value = String(value || "");

        var match = value.match(/(\d+(\.\d+)?)/);

        if (match) {
            return toNumber(match[1]);
        }

        return 0;
    }

    function parseRateFromSelectedText($row, fieldName) {
        var $ctrl = findControl($row, fieldName);

        if (!$ctrl.length || !$ctrl.is("select")) {
            return 0;
        }

        return parseRateFromText($ctrl.find("option:selected").text());
    }

    function setHeaderField(fieldName, value) {
        var rawValue = raw4(value);
        var moneyValue = money(value);

        $(
            "input[name^='value_" + fieldName + "'], " +
            "input[id^='value_" + fieldName + "'], " +
            "textarea[name^='value_" + fieldName + "'], " +
            "textarea[id^='value_" + fieldName + "']"
        ).each(function () {
            $(this).val(rawValue);
        });

        $(
            "[id^='display_value_" + fieldName + "'], " +
            "[id^='readonly_value_" + fieldName + "'], " +
            "span[id^='value_" + fieldName + "'], " +
            "div[id^='value_" + fieldName + "']"
        ).each(function () {
            var $el = $(this);

            if ($el.is("input, textarea, select")) {
                $el.val(rawValue);
            } else {
                $el.text(moneyValue);
            }
        });
    }

    function getDetailColumnMap($table) {
        var map = {};
        var foundHeader = false;

        $table.find("tr").each(function () {
            var $row = $(this);
            var rowText = normalizeText($row.text());

            if (
                rowText.indexOf("quantity") < 0 ||
                rowText.indexOf("unitprice") < 0 ||
                rowText.indexOf("linetotal") < 0
            ) {
                return true;
            }

            $row.children("th,td").each(function (index) {
                var text = normalizeText($(this).text());

                if (text === "quantity") {
                    map.quantity = index;
                } else if (text === "unitprice") {
                    map.unit_price = index;
                } else if (text === "grossamount") {
                    map.gross_amount = index;
                } else if (text === "discount" || text === "discountamount") {
                    map.discount_amount = index;
                } else if (text === "netbeforetax") {
                    map.net_before_tax = index;
                } else if (text === "vatcode") {
                    map.vat_tax_code_id = index;
                } else if (text === "vatrate" || text === "vatratepercent") {
                    map.vat_rate_percent = index;
                } else if (text === "inputvat") {
                    map.input_vat_amount = index;
                } else if (text === "withholdingtaxcode") {
                    map.withholding_tax_code_id = index;
                } else if (text === "withholding") {
                    map.withholding_amount = index;
                } else if (text === "linetotal") {
                    map.line_total_amount = index;
                }
            });

            foundHeader = true;
            return false;
        });

        if (!foundHeader) {
            return null;
        }

        if (
            map.quantity === undefined ||
            map.unit_price === undefined ||
            map.line_total_amount === undefined
        ) {
            return null;
        }

        return map;
    }

    function recalcSupplierBill() {
        var subtotal = 0;
        var discountTotal = 0;
        var inputVatTotal = 0;
        var withholdingTotal = 0;
        var grandTotal = 0;

        $("table:visible").each(function () {
            var $table = $(this);
            var col = getDetailColumnMap($table);

            if (!col) {
                return true;
            }

            $table.find("tr").each(function () {
                var $row = $(this);

                if ($row.children("th").length > 0) {
                    return true;
                }

                var rowText = normalizeText($row.text());

                if (
                    rowText.indexOf("quantity") >= 0 &&
                    rowText.indexOf("unitprice") >= 0 &&
                    rowText.indexOf("linetotal") >= 0
                ) {
                    return true;
                }

                var qty = toNumber(getRowValue($row, "quantity", col.quantity));
                var unitPrice = toNumber(getRowValue($row, "unit_price", col.unit_price));

                var existingGross = toNumber(getRowValue($row, "gross_amount", col.gross_amount));
                var existingLineTotal = toNumber(getRowValue($row, "line_total_amount", col.line_total_amount));

                if (qty <= 0 && unitPrice <= 0 && existingGross <= 0 && existingLineTotal <= 0) {
                    return true;
                }

                var discountAmount = toNumber(getRowValue($row, "discount_amount", col.discount_amount));

                var vatRate = toNumber(getRowValue($row, "vat_rate_percent", col.vat_rate_percent));

                if (vatRate <= 0) {
                    vatRate = parseRateFromSelectedText($row, "vat_tax_code_id");
                }

                if (vatRate <= 0) {
                    vatRate = parseRateFromText(getRowValue($row, "vat_tax_code_id", col.vat_tax_code_id));
                }

                var withholdingRate = toNumber(getControlValue($row, "withholding_rate_percent"));

                if (withholdingRate <= 0) {
                    withholdingRate = parseRateFromSelectedText($row, "withholding_tax_code_id");
                }

                if (withholdingRate <= 0) {
                    withholdingRate = parseRateFromText(getRowValue($row, "withholding_tax_code_id", col.withholding_tax_code_id));
                }

                var grossAmount = round4(qty * unitPrice);

                if (grossAmount <= 0 && existingGross > 0) {
                    grossAmount = existingGross;
                }

                var netBeforeTax = round4(grossAmount - discountAmount);

                if (netBeforeTax < 0) {
                    netBeforeTax = 0;
                }

                var inputVatAmount = round4(netBeforeTax * (vatRate / 100));
                var withholdingAmount = round4(netBeforeTax * (withholdingRate / 100));
                var lineTotalAmount = round4(netBeforeTax + inputVatAmount - withholdingAmount);

                setRowValue($row, "gross_amount", col.gross_amount, grossAmount);
                setRowValue($row, "discount_amount", col.discount_amount, discountAmount);
                setRowValue($row, "net_before_tax", col.net_before_tax, netBeforeTax);
                setRowValue($row, "vat_rate_percent", col.vat_rate_percent, vatRate);
                setRowValue($row, "input_vat_amount", col.input_vat_amount, inputVatAmount);
                setRowValue($row, "withholding_amount", col.withholding_amount, withholdingAmount);
                setRowValue($row, "line_total_amount", col.line_total_amount, lineTotalAmount);

                subtotal += grossAmount;
                discountTotal += discountAmount;
                inputVatTotal += inputVatAmount;
                withholdingTotal += withholdingAmount;
                grandTotal += lineTotalAmount;
            });
        });

        setHeaderField("subtotal_amount", subtotal);
        setHeaderField("discount_amount", discountTotal);
        setHeaderField("input_vat_amount", inputVatTotal);
        setHeaderField("withholding_amount", withholdingTotal);
        setHeaderField("grand_total_amount", grandTotal);
        setHeaderField("base_grand_total_amount", grandTotal);
    }

    function delayedRecalc() {
        setTimeout(recalcSupplierBill, 100);
        setTimeout(recalcSupplierBill, 300);
        setTimeout(recalcSupplierBill, 700);
    }

    $(document).on("keyup input change", "input, select, textarea", function () {
        delayedRecalc();
    });

    $(document).on("click", "a, button, input[type='button'], input[type='submit']", function () {
        delayedRecalc();
    });

    delayedRecalc();

})();
});







