<?php
class eventclass_supplier_payment_application  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(
		'discount_taken_amount' => array(
			'edit' => true 
		),
		'withholding_applied_amount' => array(
			'edit' => true 
		) 
	),
	'autoUpdateValue' => array(
		 
	),
	'uploadFolder' => array(
		 
	),
	'viewPluginInit' => array(
		 
	),
	'editPluginInit' => array(
		 
	) 
);
			}
		function BeforeAdd( &$values, &$sqlValues, &$message, $inline, $pageObject ) {
		/* ============================================================
   BuildLedger Finance - Supplier Payment Application Before Add
   ============================================================ */

if (!function_exists("bl_sp_amount")) {
    function bl_sp_amount($value) {
        $value = str_replace(",", "", (string)$value);
        return round((float)$value, 4);
    }
}

if (empty($values["supplier_payment_id"])) {
    $message = "Supplier payment header is missing.";
    return false;
}

if (empty($values["supplier_bill_id"])) {
    $message = "Please select the supplier bill to apply this payment to.";
    return false;
}

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

/* ============================================================
   Check Supplier Payment Header
   ============================================================ */

$rsPayment = DB::Query("
    SELECT
        id,
        accounting_period_id,
        posting_status,
        COALESCE(gross_payment_amount, 0) AS gross_payment_amount,
        COALESCE(withholding_amount, 0) AS withholding_amount,
        COALESCE(bank_charge_amount, 0) AS bank_charge_amount,
        COALESCE(net_cash_amount, 0) AS net_cash_amount
    FROM supplier_payment
    WHERE id = " . $supplierPaymentId . "
    LIMIT 1
");

$payment = $rsPayment->fetchAssoc();

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

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

/* ============================================================
   Period Lock Check
   ============================================================ */

$accountingPeriodId = (int)$payment["accounting_period_id"];

if ($accountingPeriodId > 0) {
    $rsPeriod = DB::Query("
        SELECT period_status
        FROM accounting_period
        WHERE id = " . $accountingPeriodId . "
        LIMIT 1
    ");

    $period = $rsPeriod->fetchAssoc();

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

    if (strtoupper($period["period_status"]) == "CLOSED") {
        $message = "This accounting period is already closed. You cannot add supplier payment applications.";
        return false;
    }
}

/* ============================================================
   Check Supplier Bill
   ============================================================ */

$rsBill = DB::Query("
    SELECT
        id,
        bill_no,
        COALESCE(grand_total_amount, 0) AS grand_total_amount,
        document_status,
        posting_status
    FROM supplier_bill
    WHERE id = " . $supplierBillId . "
    LIMIT 1
");

$bill = $rsBill->fetchAssoc();

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

if (strtoupper($bill["document_status"]) == "CANCELLED") {
    $message = "Cannot apply payment to a cancelled supplier bill.";
    return false;
}

/* ============================================================
   Clean Amounts
   ============================================================ */

$values["supplier_bill_id"] = $supplierBillId;

$values["applied_amount"] = !empty($values["applied_amount"])
    ? bl_sp_amount($values["applied_amount"])
    : 0;

$values["discount_taken_amount"] = !empty($values["discount_taken_amount"])
    ? bl_sp_amount($values["discount_taken_amount"])
    : 0;

$values["withholding_applied_amount"] = !empty($values["withholding_applied_amount"])
    ? bl_sp_amount($values["withholding_applied_amount"])
    : 0;

$totalSettlement =
    $values["applied_amount"] +
    $values["discount_taken_amount"] +
    $values["withholding_applied_amount"];

if ($totalSettlement <= 0) {
    $message = "Applied amount, discount, or withholding must be greater than zero.";
    return false;
}

/* ============================================================
   Validate Against Supplier Payment Available Cash
   ============================================================ */

$grossPaymentAmount = bl_sp_amount($payment["gross_payment_amount"]);
$headerWithholding  = bl_sp_amount($payment["withholding_amount"]);
$bankChargeAmount   = bl_sp_amount($payment["bank_charge_amount"]);

$netCashAmount = $grossPaymentAmount - $headerWithholding - $bankChargeAmount;

if ($netCashAmount < 0) {
    $netCashAmount = 0;
}

$rsExistingPaymentApps = DB::Query("
    SELECT
        COALESCE(SUM(applied_amount), 0) AS total_applied_amount
    FROM supplier_payment_application
    WHERE supplier_payment_id = " . $supplierPaymentId . "
");

$existingPaymentApps = $rsExistingPaymentApps->fetchAssoc();
$currentAppliedTotal = bl_sp_amount($existingPaymentApps["total_applied_amount"]);

if (($currentAppliedTotal + $values["applied_amount"]) > ($netCashAmount + 0.004)) {
    $message = "Total applied amount cannot exceed the net cash payment amount.";
    return false;
}

/* ============================================================
   Validate Against Supplier Bill Balance
   ============================================================ */

$rsExistingBillApps = DB::Query("
    SELECT
        COALESCE(SUM(applied_amount + discount_taken_amount + withholding_applied_amount), 0) AS total_bill_settlement
    FROM supplier_payment_application
    WHERE supplier_bill_id = " . $supplierBillId . "
");

$existingBillApps = $rsExistingBillApps->fetchAssoc();
$currentBillSettlement = bl_sp_amount($existingBillApps["total_bill_settlement"]);

$billGrandTotal = bl_sp_amount($bill["grand_total_amount"]);

if (($currentBillSettlement + $totalSettlement) > ($billGrandTotal + 0.004)) {
    $message = "Total applied, discount, and withholding cannot exceed the supplier bill total.";
    return false;
}

if (empty($values["applied_at"])) {
    $values["applied_at"] = date("Y-m-d");
}

return true;
		;
		return true;
	}

	function BeforeEdit( &$values, &$sqlValues, $where, &$oldvalues, &$keys, &$message, $inline, $pageObject ) {
		/* ============================================================
   BuildLedger Finance - Supplier Payment Application Before Edit
   ============================================================ */

if (!function_exists("bl_sp_amount")) {
    function bl_sp_amount($value) {
        $value = str_replace(",", "", (string)$value);
        return round((float)$value, 4);
    }
}

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

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

$supplierPaymentId = (int)$values["supplier_payment_id"];
$supplierBillId    = (int)$values["supplier_bill_id"];
$applicationId     = (int)$oldvalues["id"];

/* ============================================================
   Check Supplier Payment Header
   ============================================================ */

$rsPayment = DB::Query("
    SELECT
        id,
        accounting_period_id,
        posting_status,
        COALESCE(gross_payment_amount, 0) AS gross_payment_amount,
        COALESCE(withholding_amount, 0) AS withholding_amount,
        COALESCE(bank_charge_amount, 0) AS bank_charge_amount,
        COALESCE(net_cash_amount, 0) AS net_cash_amount
    FROM supplier_payment
    WHERE id = " . $supplierPaymentId . "
    LIMIT 1
");

$payment = $rsPayment->fetchAssoc();

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

if (strtoupper($payment["posting_status"]) == "POSTED") {
    $message = "Cannot edit applications of a posted supplier payment.";
    return false;
}

/* ============================================================
   Period Lock Check
   ============================================================ */

$accountingPeriodId = (int)$payment["accounting_period_id"];

if ($accountingPeriodId > 0) {
    $rsPeriod = DB::Query("
        SELECT period_status
        FROM accounting_period
        WHERE id = " . $accountingPeriodId . "
        LIMIT 1
    ");

    $period = $rsPeriod->fetchAssoc();

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

    if (strtoupper($period["period_status"]) == "CLOSED") {
        $message = "This accounting period is already closed. You cannot edit supplier payment applications.";
        return false;
    }
}

/* ============================================================
   Check Supplier Bill
   ============================================================ */

$rsBill = DB::Query("
    SELECT
        id,
        bill_no,
        COALESCE(grand_total_amount, 0) AS grand_total_amount,
        document_status,
        posting_status
    FROM supplier_bill
    WHERE id = " . $supplierBillId . "
    LIMIT 1
");

$bill = $rsBill->fetchAssoc();

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

if (strtoupper($bill["document_status"]) == "CANCELLED") {
    $message = "Cannot apply payment to a cancelled supplier bill.";
    return false;
}

/* ============================================================
   Clean Amounts
   ============================================================ */

$values["supplier_bill_id"] = $supplierBillId;

$values["applied_amount"] = !empty($values["applied_amount"])
    ? bl_sp_amount($values["applied_amount"])
    : 0;

$values["discount_taken_amount"] = !empty($values["discount_taken_amount"])
    ? bl_sp_amount($values["discount_taken_amount"])
    : 0;

$values["withholding_applied_amount"] = !empty($values["withholding_applied_amount"])
    ? bl_sp_amount($values["withholding_applied_amount"])
    : 0;

$totalSettlement =
    $values["applied_amount"] +
    $values["discount_taken_amount"] +
    $values["withholding_applied_amount"];

if ($totalSettlement <= 0) {
    $message = "Applied amount, discount, or withholding must be greater than zero.";
    return false;
}

/* ============================================================
   Validate Against Supplier Payment Available Cash
   ============================================================ */

$grossPaymentAmount = bl_sp_amount($payment["gross_payment_amount"]);
$headerWithholding  = bl_sp_amount($payment["withholding_amount"]);
$bankChargeAmount   = bl_sp_amount($payment["bank_charge_amount"]);

$netCashAmount = $grossPaymentAmount - $headerWithholding - $bankChargeAmount;

if ($netCashAmount < 0) {
    $netCashAmount = 0;
}

$rsExistingPaymentApps = DB::Query("
    SELECT
        COALESCE(SUM(applied_amount), 0) AS total_applied_amount
    FROM supplier_payment_application
    WHERE supplier_payment_id = " . $supplierPaymentId . "
      AND id <> " . $applicationId . "
");

$existingPaymentApps = $rsExistingPaymentApps->fetchAssoc();
$currentAppliedTotal = bl_sp_amount($existingPaymentApps["total_applied_amount"]);

if (($currentAppliedTotal + $values["applied_amount"]) > ($netCashAmount + 0.004)) {
    $message = "Total applied amount cannot exceed the net cash payment amount.";
    return false;
}

/* ============================================================
   Validate Against Supplier Bill Balance
   ============================================================ */

$rsExistingBillApps = DB::Query("
    SELECT
        COALESCE(SUM(applied_amount + discount_taken_amount + withholding_applied_amount), 0) AS total_bill_settlement
    FROM supplier_payment_application
    WHERE supplier_bill_id = " . $supplierBillId . "
      AND id <> " . $applicationId . "
");

$existingBillApps = $rsExistingBillApps->fetchAssoc();
$currentBillSettlement = bl_sp_amount($existingBillApps["total_bill_settlement"]);

$billGrandTotal = bl_sp_amount($bill["grand_total_amount"]);

if (($currentBillSettlement + $totalSettlement) > ($billGrandTotal + 0.004)) {
    $message = "Total applied, discount, and withholding cannot exceed the supplier bill total.";
    return false;
}

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

return true;
		;
		return true;
	}

	function AfterAdd( &$values, &$keys, $inline, $pageObject ) {
		// BuildLedger Finance - Recalculate Supplier Payment Applied/Unapplied
// Updated to use net_cash_amount.

$supplierPaymentIds = array();

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

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

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

$supplierPaymentIds = array_unique($supplierPaymentIds);

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

foreach ($supplierPaymentIds as $supplierPaymentId) {

    $rsPayment = DB::Query("
        SELECT net_cash_amount AS net_paid_amount
        FROM supplier_payment
        WHERE id = " . (int)$supplierPaymentId . "
        LIMIT 1
    ");

    $payment = $rsPayment->fetchAssoc();

    if (!$payment) {
        continue;
    }

    $rsApplied = DB::Query("
        SELECT COALESCE(SUM(applied_amount), 0) AS applied_amount
        FROM supplier_payment_application
        WHERE supplier_payment_id = " . (int)$supplierPaymentId
    );

    $applied = $rsApplied->fetchAssoc();

    $netPaidAmount = (float)$payment["net_paid_amount"];
    $appliedAmount = $applied ? (float)$applied["applied_amount"] : 0;
    $unappliedAmount = round($netPaidAmount - $appliedAmount, 4);

    DB::Exec("
        UPDATE supplier_payment
        SET
            applied_amount = " . $fmt($appliedAmount) . ",
            unapplied_amount = " . $fmt($unappliedAmount) . "
        WHERE id = " . (int)$supplierPaymentId . "
        LIMIT 1
    ");
}
		;
		
	}

	function AfterEdit( &$values, $where, &$oldvalues, &$keys, $inline, $pageObject ) {
		// BuildLedger Finance - Recalculate Supplier Payment Applied/Unapplied
// Updated to use net_cash_amount.

$supplierPaymentIds = array();

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

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

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

$supplierPaymentIds = array_unique($supplierPaymentIds);

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

foreach ($supplierPaymentIds as $supplierPaymentId) {

    $rsPayment = DB::Query("
        SELECT net_cash_amount AS net_paid_amount
        FROM supplier_payment
        WHERE id = " . (int)$supplierPaymentId . "
        LIMIT 1
    ");

    $payment = $rsPayment->fetchAssoc();

    if (!$payment) {
        continue;
    }

    $rsApplied = DB::Query("
        SELECT COALESCE(SUM(applied_amount), 0) AS applied_amount
        FROM supplier_payment_application
        WHERE supplier_payment_id = " . (int)$supplierPaymentId
    );

    $applied = $rsApplied->fetchAssoc();

    $netPaidAmount = (float)$payment["net_paid_amount"];
    $appliedAmount = $applied ? (float)$applied["applied_amount"] : 0;
    $unappliedAmount = round($netPaidAmount - $appliedAmount, 4);

    DB::Exec("
        UPDATE supplier_payment
        SET
            applied_amount = " . $fmt($appliedAmount) . ",
            unapplied_amount = " . $fmt($unappliedAmount) . "
        WHERE id = " . (int)$supplierPaymentId . "
        LIMIT 1
    ");
}
		;
		
	}

	function AfterDelete( $where, &$deleted_values, &$message, $pageObject ) {
		// BuildLedger Finance - Recalculate Supplier Payment Applied/Unapplied
// Updated to use net_cash_amount.

$supplierPaymentIds = array();

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

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

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

$supplierPaymentIds = array_unique($supplierPaymentIds);

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

foreach ($supplierPaymentIds as $supplierPaymentId) {

    $rsPayment = DB::Query("
        SELECT net_cash_amount AS net_paid_amount
        FROM supplier_payment
        WHERE id = " . (int)$supplierPaymentId . "
        LIMIT 1
    ");

    $payment = $rsPayment->fetchAssoc();

    if (!$payment) {
        continue;
    }

    $rsApplied = DB::Query("
        SELECT COALESCE(SUM(applied_amount), 0) AS applied_amount
        FROM supplier_payment_application
        WHERE supplier_payment_id = " . (int)$supplierPaymentId
    );

    $applied = $rsApplied->fetchAssoc();

    $netPaidAmount = (float)$payment["net_paid_amount"];
    $appliedAmount = $applied ? (float)$applied["applied_amount"] : 0;
    $unappliedAmount = round($netPaidAmount - $appliedAmount, 4);

    DB::Exec("
        UPDATE supplier_payment
        SET
            applied_amount = " . $fmt($appliedAmount) . ",
            unapplied_amount = " . $fmt($unappliedAmount) . "
        WHERE id = " . (int)$supplierPaymentId . "
        LIMIT 1
    ");
}
		;
		
	}

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

$supplierPaymentId = !empty($deleted_values["supplier_payment_id"])
    ? (int)$deleted_values["supplier_payment_id"]
    : 0;

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

// Check parent supplier payment
$rsPayment = DB::Query("
    SELECT
        sp.id,
        sp.posting_status,
        sp.accounting_period_id,
        ap.period_status
    FROM supplier_payment sp
    LEFT JOIN accounting_period ap
        ON ap.id = sp.accounting_period_id
    WHERE sp.id = " . $supplierPaymentId . "
    LIMIT 1
");

$payment = $rsPayment->fetchAssoc();

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

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

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

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

return true;
		;
		return true;
	}
	public function default_discount_taken_amount_efedit(  ) {
	$defaultValue = 0;
return $defaultValue;
}

public function default_withholding_applied_amount_efedit(  ) {
	$defaultValue = 0;
return $defaultValue;
}	

}


?>