<?php
class eventclass_supplier_bill_detail  extends TableEventsBase {
	
	function init() {
		$this->events = array(
	'BeforeAdd' => true,
	'BeforeEdit' => true,
	'AfterAdd' => true,
	'AfterEdit' => true,
	'AfterDelete' => true,
	'BeforeDelete' => true 
);
		$this->fieldValues = array(
	'filterLimit' => array(
		 
	),
	'mapIcon' => array(
		 
	),
	'viewCustom' => array(
		 
	),
	'lookupWhere' => array(
		 
	),
	'viewFileText' => array(
		 
	),
	'defaultValue' => array(
		 
	),
	'autoUpdateValue' => array(
		 
	),
	'uploadFolder' => array(
		 
	),
	'viewPluginInit' => array(
		 
	),
	'editPluginInit' => array(
		 
	) 
);
			}
		function BeforeAdd( &$values, &$sqlValues, &$message, $inline, $pageObject ) {
		// BuildLedger Finance - Supplier Bill Detail Before Add

// UUID
if (empty($values["supplier_bill_detail_uuid"])) {
    $rs = DB::Query("SELECT UUID() AS uuid");
    $data = $rs->fetchAssoc();
    $values["supplier_bill_detail_uuid"] = $data["uuid"];
}

// Validate master supplier_bill_id
if (empty($values["supplier_bill_id"])) {
    $message = "Supplier bill header is missing.";
    return false;
}

$supplierBillId = (int) $values["supplier_bill_id"];
/* ============================================================
   Period Lock Check - Supplier Bill Detail Add
   ============================================================ */

$checkSupplierBillId = 0;

if (!empty($values["supplier_bill_id"])) {
    $checkSupplierBillId = (int)$values["supplier_bill_id"];
}

if ($checkSupplierBillId > 0) {
    $rsPeriod = DB::Query("
        SELECT
            ap.period_status
        FROM supplier_bill sb
        INNER JOIN accounting_period ap
            ON ap.id = sb.accounting_period_id
        WHERE sb.id = " . $checkSupplierBillId . "
        LIMIT 1
    ");

    $period = $rsPeriod->fetchAssoc();

    if (!$period) {
        $message = "Accounting period was not found for this supplier bill.";
        return false;
    }

    if (strtoupper($period["period_status"]) == "CLOSED") {
        $message = "This accounting period is already closed. You cannot add supplier bill detail lines.";
        return false;
    }
}
$rs = DB::Query("
    SELECT posting_status, exchange_rate
    FROM supplier_bill
    WHERE id = " . $supplierBillId . "
    LIMIT 1
");

$bill = $rs->fetchAssoc();

if (!$bill) {
    $message = "Supplier bill header was not found.";
    return false;
}

if ($bill["posting_status"] == "POSTED") {
    $message = "Cannot add lines to a posted supplier bill.";
    return false;
}

// Line number default
if (empty($values["line_no"])) {
    $rs = DB::Query("
        SELECT COALESCE(MAX(line_no), 0) + 1 AS next_line_no
        FROM supplier_bill_detail
        WHERE supplier_bill_id = " . $supplierBillId
    );

    $data = $rs->fetchAssoc();
    $values["line_no"] = (int) $data["next_line_no"];
}

// Item defaults
if (!empty($values["item_id"])) {
    $itemId = (int) $values["item_id"];

    $rsItem = DB::Query("
        SELECT
            item_code,
            item_name,
            uom_code
        FROM item
        WHERE id = " . $itemId . "
        LIMIT 1
    ");

    $item = $rsItem->fetchAssoc();

    if ($item) {
        if (empty($values["description"])) {
            $values["description"] = $item["item_name"];
        }

        if (empty($values["uom_code"])) {
            $values["uom_code"] = $item["uom_code"];
        }
    }
}

// VAT rate
if (!empty($values["vat_tax_code_id"])) {
    $vatTaxCodeId = (int) $values["vat_tax_code_id"];

    $rsVat = DB::Query("
        SELECT rate_percent
        FROM tax_code
        WHERE id = " . $vatTaxCodeId . "
        LIMIT 1
    ");

    $vat = $rsVat->fetchAssoc();

    if ($vat) {
        $values["vat_rate_percent"] = (float) $vat["rate_percent"];
    }
}

// Withholding rate
if (!empty($values["withholding_tax_code_id"])) {
    $withholdingTaxCodeId = (int) $values["withholding_tax_code_id"];

    $rsWh = DB::Query("
        SELECT rate_percent
        FROM tax_code
        WHERE id = " . $withholdingTaxCodeId . "
        LIMIT 1
    ");

    $wh = $rsWh->fetchAssoc();

    if ($wh) {
        $values["withholding_rate_percent"] = (float) $wh["rate_percent"];
    }
}

// Numeric defaults
$qty = !empty($values["quantity"]) ? (float) $values["quantity"] : 0;
$unitPrice = !empty($values["unit_price"]) ? (float) $values["unit_price"] : 0;

$discountAmount = !empty($values["discount_amount"])
    ? (float) $values["discount_amount"]
    : 0;

$vatRate = !empty($values["vat_rate_percent"])
    ? (float) $values["vat_rate_percent"]
    : 0;

$withholdingRate = !empty($values["withholding_rate_percent"])
    ? (float) $values["withholding_rate_percent"]
    : 0;

if ($qty <= 0) {
    $message = "Quantity must be greater than zero.";
    return false;
}

if ($unitPrice < 0) {
    $message = "Unit price cannot be negative.";
    return false;
}

$gross = round($qty * $unitPrice, 4);
$netBeforeTax = round($gross - $discountAmount, 4);

if ($netBeforeTax < 0) {
    $message = "Discount cannot exceed the line amount.";
    return false;
}

$inputVatAmount = round($netBeforeTax * ($vatRate / 100), 4);
$withholdingAmount = round($netBeforeTax * ($withholdingRate / 100), 4);
$lineTotal = round($netBeforeTax + $inputVatAmount - $withholdingAmount, 4);

// Save cleaned/calculated values
$values["quantity"] = $qty;
$values["unit_price"] = $unitPrice;
$values["gross_amount"] = $gross;
$values["discount_amount"] = $discountAmount;
$values["net_before_tax"] = $netBeforeTax;
$values["vat_rate_percent"] = $vatRate;
$values["input_vat_amount"] = $inputVatAmount;
$values["withholding_rate_percent"] = $withholdingRate;
$values["withholding_amount"] = $withholdingAmount;
$values["line_total_amount"] = $lineTotal;

return true;
		;
		return true;
	}

	function BeforeEdit( &$values, &$sqlValues, $where, &$oldvalues, &$keys, &$message, $inline, $pageObject ) {
		// BuildLedger Finance - Supplier Bill Detail Before Edit

if (empty($values["supplier_bill_id"])) {
    $values["supplier_bill_id"] = $oldvalues["supplier_bill_id"];
}

$supplierBillId = (int) $values["supplier_bill_id"];

$rs = DB::Query("
    SELECT posting_status, exchange_rate
    FROM supplier_bill
    WHERE id = " . $supplierBillId . "
    LIMIT 1
");

$bill = $rs->fetchAssoc();

if (!$bill) {
    $message = "Supplier bill header was not found.";
    return false;
}

if ($bill["posting_status"] == "POSTED") {
    $message = "Cannot edit lines of a posted supplier bill.";
    return false;
}
/* ============================================================
   Period Lock Check - Supplier Bill Detail Edit
   ============================================================ */

$checkSupplierBillId = 0;

if (!empty($oldvalues["supplier_bill_id"])) {
    $checkSupplierBillId = (int)$oldvalues["supplier_bill_id"];
} elseif (!empty($values["supplier_bill_id"])) {
    $checkSupplierBillId = (int)$values["supplier_bill_id"];
}

if ($checkSupplierBillId > 0) {
    $rsPeriod = DB::Query("
        SELECT
            ap.period_status
        FROM supplier_bill sb
        INNER JOIN accounting_period ap
            ON ap.id = sb.accounting_period_id
        WHERE sb.id = " . $checkSupplierBillId . "
        LIMIT 1
    ");

    $period = $rsPeriod->fetchAssoc();

    if (!$period) {
        $message = "Accounting period was not found for this supplier bill.";
        return false;
    }

    if (strtoupper($period["period_status"]) == "CLOSED") {
        $message = "This accounting period is already closed. You cannot edit supplier bill detail lines.";
        return false;
    }
}
// Keep system fields
$values["supplier_bill_detail_uuid"] = $oldvalues["supplier_bill_detail_uuid"];
$values["supplier_bill_id"] = $oldvalues["supplier_bill_id"];

// Item defaults
if (!empty($values["item_id"])) {
    $itemId = (int) $values["item_id"];

    $rsItem = DB::Query("
        SELECT
            item_code,
            item_name,
            uom_code
        FROM item
        WHERE id = " . $itemId . "
        LIMIT 1
    ");

    $item = $rsItem->fetchAssoc();

    if ($item) {
        if (empty($values["description"])) {
            $values["description"] = $item["item_name"];
        }

        if (empty($values["uom_code"])) {
            $values["uom_code"] = $item["uom_code"];
        }
    }
}

// VAT rate
if (!empty($values["vat_tax_code_id"])) {
    $vatTaxCodeId = (int) $values["vat_tax_code_id"];

    $rsVat = DB::Query("
        SELECT rate_percent
        FROM tax_code
        WHERE id = " . $vatTaxCodeId . "
        LIMIT 1
    ");

    $vat = $rsVat->fetchAssoc();

    if ($vat) {
        $values["vat_rate_percent"] = (float) $vat["rate_percent"];
    }
}

// Withholding rate
if (!empty($values["withholding_tax_code_id"])) {
    $withholdingTaxCodeId = (int) $values["withholding_tax_code_id"];

    $rsWh = DB::Query("
        SELECT rate_percent
        FROM tax_code
        WHERE id = " . $withholdingTaxCodeId . "
        LIMIT 1
    ");

    $wh = $rsWh->fetchAssoc();

    if ($wh) {
        $values["withholding_rate_percent"] = (float) $wh["rate_percent"];
    }
}

// Numeric defaults
$qty = !empty($values["quantity"]) ? (float) $values["quantity"] : 0;
$unitPrice = !empty($values["unit_price"]) ? (float) $values["unit_price"] : 0;

$discountAmount = !empty($values["discount_amount"])
    ? (float) $values["discount_amount"]
    : 0;

$vatRate = !empty($values["vat_rate_percent"])
    ? (float) $values["vat_rate_percent"]
    : 0;

$withholdingRate = !empty($values["withholding_rate_percent"])
    ? (float) $values["withholding_rate_percent"]
    : 0;

if ($qty <= 0) {
    $message = "Quantity must be greater than zero.";
    return false;
}

if ($unitPrice < 0) {
    $message = "Unit price cannot be negative.";
    return false;
}

$gross = round($qty * $unitPrice, 4);
$netBeforeTax = round($gross - $discountAmount, 4);

if ($netBeforeTax < 0) {
    $message = "Discount cannot exceed the line amount.";
    return false;
}

$inputVatAmount = round($netBeforeTax * ($vatRate / 100), 4);
$withholdingAmount = round($netBeforeTax * ($withholdingRate / 100), 4);
$lineTotal = round($netBeforeTax + $inputVatAmount - $withholdingAmount, 4);

// Save cleaned/calculated values
$values["quantity"] = $qty;
$values["unit_price"] = $unitPrice;
$values["gross_amount"] = $gross;
$values["discount_amount"] = $discountAmount;
$values["net_before_tax"] = $netBeforeTax;
$values["vat_rate_percent"] = $vatRate;
$values["input_vat_amount"] = $inputVatAmount;
$values["withholding_rate_percent"] = $withholdingRate;
$values["withholding_amount"] = $withholdingAmount;
$values["line_total_amount"] = $lineTotal;

return true;
		;
		return true;
	}

	function AfterAdd( &$values, &$keys, $inline, $pageObject ) {
		// BuildLedger Finance - Recalculate Supplier Bill Header Totals

$supplierBillIds = array();

if (isset($values["supplier_bill_id"]) && (int)$values["supplier_bill_id"] > 0) {
    $supplierBillIds[] = (int)$values["supplier_bill_id"];
}

if (isset($oldvalues["supplier_bill_id"]) && (int)$oldvalues["supplier_bill_id"] > 0) {
    $supplierBillIds[] = (int)$oldvalues["supplier_bill_id"];
}

if (isset($deleted_values["supplier_bill_id"]) && (int)$deleted_values["supplier_bill_id"] > 0) {
    $supplierBillIds[] = (int)$deleted_values["supplier_bill_id"];
}

$supplierBillIds = array_unique($supplierBillIds);

$fmt = function ($value) {
    return number_format((float)$value, 4, ".", "");
};

foreach ($supplierBillIds as $supplierBillId) {

    $rs = DB::Query("
        SELECT
            COALESCE(SUM(gross_amount), 0) AS subtotal_amount,
            COALESCE(SUM(discount_amount), 0) AS discount_amount,
            COALESCE(SUM(input_vat_amount), 0) AS input_vat_amount,
            COALESCE(SUM(withholding_amount), 0) AS withholding_amount,
            COALESCE(SUM(line_total_amount), 0) AS grand_total_amount
        FROM supplier_bill_detail
        WHERE supplier_bill_id = " . (int)$supplierBillId
    );

    $totals = $rs->fetchAssoc();

    $rsBill = DB::Query("
        SELECT exchange_rate
        FROM supplier_bill
        WHERE id = " . (int)$supplierBillId . "
        LIMIT 1
    ");

    $bill = $rsBill->fetchAssoc();
    $exchangeRate = !empty($bill["exchange_rate"]) ? (float)$bill["exchange_rate"] : 1;

    $baseGrandTotal = round((float)$totals["grand_total_amount"] * $exchangeRate, 4);

    DB::Exec("
        UPDATE supplier_bill
        SET
            subtotal_amount = " . $fmt($totals["subtotal_amount"]) . ",
            discount_amount = " . $fmt($totals["discount_amount"]) . ",
            input_vat_amount = " . $fmt($totals["input_vat_amount"]) . ",
            withholding_amount = " . $fmt($totals["withholding_amount"]) . ",
            grand_total_amount = " . $fmt($totals["grand_total_amount"]) . ",
            base_grand_total_amount = " . $fmt($baseGrandTotal) . "
        WHERE id = " . (int)$supplierBillId . "
        LIMIT 1
    ");
}
		;
		
	}

	function AfterEdit( &$values, $where, &$oldvalues, &$keys, $inline, $pageObject ) {
		// BuildLedger Finance - Recalculate Supplier Bill Header Totals

$supplierBillIds = array();

if (isset($values["supplier_bill_id"]) && (int)$values["supplier_bill_id"] > 0) {
    $supplierBillIds[] = (int)$values["supplier_bill_id"];
}

if (isset($oldvalues["supplier_bill_id"]) && (int)$oldvalues["supplier_bill_id"] > 0) {
    $supplierBillIds[] = (int)$oldvalues["supplier_bill_id"];
}

if (isset($deleted_values["supplier_bill_id"]) && (int)$deleted_values["supplier_bill_id"] > 0) {
    $supplierBillIds[] = (int)$deleted_values["supplier_bill_id"];
}

$supplierBillIds = array_unique($supplierBillIds);

$fmt = function ($value) {
    return number_format((float)$value, 4, ".", "");
};

foreach ($supplierBillIds as $supplierBillId) {

    $rs = DB::Query("
        SELECT
            COALESCE(SUM(gross_amount), 0) AS subtotal_amount,
            COALESCE(SUM(discount_amount), 0) AS discount_amount,
            COALESCE(SUM(input_vat_amount), 0) AS input_vat_amount,
            COALESCE(SUM(withholding_amount), 0) AS withholding_amount,
            COALESCE(SUM(line_total_amount), 0) AS grand_total_amount
        FROM supplier_bill_detail
        WHERE supplier_bill_id = " . (int)$supplierBillId
    );

    $totals = $rs->fetchAssoc();

    $rsBill = DB::Query("
        SELECT exchange_rate
        FROM supplier_bill
        WHERE id = " . (int)$supplierBillId . "
        LIMIT 1
    ");

    $bill = $rsBill->fetchAssoc();
    $exchangeRate = !empty($bill["exchange_rate"]) ? (float)$bill["exchange_rate"] : 1;

    $baseGrandTotal = round((float)$totals["grand_total_amount"] * $exchangeRate, 4);

    DB::Exec("
        UPDATE supplier_bill
        SET
            subtotal_amount = " . $fmt($totals["subtotal_amount"]) . ",
            discount_amount = " . $fmt($totals["discount_amount"]) . ",
            input_vat_amount = " . $fmt($totals["input_vat_amount"]) . ",
            withholding_amount = " . $fmt($totals["withholding_amount"]) . ",
            grand_total_amount = " . $fmt($totals["grand_total_amount"]) . ",
            base_grand_total_amount = " . $fmt($baseGrandTotal) . "
        WHERE id = " . (int)$supplierBillId . "
        LIMIT 1
    ");
}
		;
		
	}

	function AfterDelete( $where, &$deleted_values, &$message, $pageObject ) {
		// BuildLedger Finance - Recalculate Supplier Bill Header Totals

$supplierBillIds = array();

if (isset($values["supplier_bill_id"]) && (int)$values["supplier_bill_id"] > 0) {
    $supplierBillIds[] = (int)$values["supplier_bill_id"];
}

if (isset($oldvalues["supplier_bill_id"]) && (int)$oldvalues["supplier_bill_id"] > 0) {
    $supplierBillIds[] = (int)$oldvalues["supplier_bill_id"];
}

if (isset($deleted_values["supplier_bill_id"]) && (int)$deleted_values["supplier_bill_id"] > 0) {
    $supplierBillIds[] = (int)$deleted_values["supplier_bill_id"];
}

$supplierBillIds = array_unique($supplierBillIds);

$fmt = function ($value) {
    return number_format((float)$value, 4, ".", "");
};

foreach ($supplierBillIds as $supplierBillId) {

    $rs = DB::Query("
        SELECT
            COALESCE(SUM(gross_amount), 0) AS subtotal_amount,
            COALESCE(SUM(discount_amount), 0) AS discount_amount,
            COALESCE(SUM(input_vat_amount), 0) AS input_vat_amount,
            COALESCE(SUM(withholding_amount), 0) AS withholding_amount,
            COALESCE(SUM(line_total_amount), 0) AS grand_total_amount
        FROM supplier_bill_detail
        WHERE supplier_bill_id = " . (int)$supplierBillId
    );

    $totals = $rs->fetchAssoc();

    $rsBill = DB::Query("
        SELECT exchange_rate
        FROM supplier_bill
        WHERE id = " . (int)$supplierBillId . "
        LIMIT 1
    ");

    $bill = $rsBill->fetchAssoc();
    $exchangeRate = !empty($bill["exchange_rate"]) ? (float)$bill["exchange_rate"] : 1;

    $baseGrandTotal = round((float)$totals["grand_total_amount"] * $exchangeRate, 4);

    DB::Exec("
        UPDATE supplier_bill
        SET
            subtotal_amount = " . $fmt($totals["subtotal_amount"]) . ",
            discount_amount = " . $fmt($totals["discount_amount"]) . ",
            input_vat_amount = " . $fmt($totals["input_vat_amount"]) . ",
            withholding_amount = " . $fmt($totals["withholding_amount"]) . ",
            grand_total_amount = " . $fmt($totals["grand_total_amount"]) . ",
            base_grand_total_amount = " . $fmt($baseGrandTotal) . "
        WHERE id = " . (int)$supplierBillId . "
        LIMIT 1
    ");
}
		;
		
	}

	function BeforeDelete( $where, &$deleted_values, &$message, $pageObject ) {
		// BuildLedger Finance - Supplier Bill Detail Before Delete

$supplierBillId = !empty($deleted_values["supplier_bill_id"])
    ? (int)$deleted_values["supplier_bill_id"]
    : 0;

if ($supplierBillId <= 0) {
    $message = "Supplier bill header is missing.";
    return false;
}

// Check parent supplier bill
$rsBill = DB::Query("
    SELECT
        sb.id,
        sb.posting_status,
        sb.accounting_period_id,
        ap.period_status
    FROM supplier_bill sb
    LEFT JOIN accounting_period ap
        ON ap.id = sb.accounting_period_id
    WHERE sb.id = " . $supplierBillId . "
    LIMIT 1
");

$bill = $rsBill->fetchAssoc();

if (!$bill) {
    $message = "Supplier bill was not found.";
    return false;
}

// Block delete if parent supplier bill is posted
if (strtoupper((string)$bill["posting_status"]) == "POSTED") {
    $message = "This supplier bill is already posted. You cannot delete detail lines.";
    return false;
}

// Block delete if accounting period is missing
if (empty($bill["period_status"])) {
    $message = "Accounting period was not found for this supplier bill.";
    return false;
}

// Block delete if accounting period is closed
if (strtoupper((string)$bill["period_status"]) == "CLOSED") {
    $message = "This accounting period is already closed. You cannot delete supplier bill detail lines.";
    return false;
}

return true;
		;
		return true;
	}
		

}


?>