/**
  * Updates payments schedules accumulated interest/surcharges.
  *
  *
  **/
 function updatePaymentSchedulesInterestSurcharges(&$trans_obj)
 {
     // retrieve payment schedule list which are not yet fully paid
     //$tps_records = $this->listPaymentSchedule( $trans_obj->getData(TRANS_ID), TPS_PAYMENT_STATE_UNPAID, TPS_PAYMENT_DUE_DATE, false );
     $tps_records = $this->listSynchPaymentSchedule($trans_obj->getData(TRANS_ID), TPS_PAYMENT_STATE_UNPAID, TPS_PAYMENT_DUE_DATE, false);
     if (is_array($tps_records)) {
         $tmp_tps_included_records = NULL;
         mysql_query("LOCK TABLES", $this->m_dbLink);
         $clsAccounts = new EBPLChartOfAccountsSysRef($this->m_dbLink, false);
         $cash_account_code = $clsAccounts->getCashAccountCode();
         if ($cash_account_code < 0) {
             $this->debug(-5, "Unable to load cash account code, return {$cash_account_code}!");
             $this->setError(-5, "Unable to load cash account code, return {$cash_account_code}!");
             return -5;
         }
         for ($i = 0; $i < count($tps_records); $i++) {
             // ---- LOAD TRANSACTOPM RECORD DATA
             $payment_id = $tps_records[$i]->getData(TPS_PAYMENT_ID);
             $fee_id = $tps_records[$i]->getData(TPS_PAYMENT_FEE_ID);
             $tax_fee_code = $tps_records[$i]->getData(TPS_PAYMENT_TAX_FEE_CODE);
             $tps_amount_due = $tps_records[$i]->getData(TPS_PAYMENT_TOTAL_AMOUNT_DUE);
             $tps_amount_paid = $tps_records[$i]->getData(TPS_PAYMENT_AMOUNT_PAID);
             $tps_penalty_amount = $tps_records[$i]->getData(TPS_PAYMENT_PENALTY_AMOUNT);
             $tps_penalty_amount_paid = $tps_records[$i]->getData(TPS_PAYMENT_PENALTY_AMOUNT_PAID);
             $tps_interest_amount = $tps_records[$i]->getData(TPS_PAYMENT_INTEREST_AMOUNT);
             $tps_interest_amount_paid = $tps_records[$i]->getData(TPS_PAYMENT_INTEREST_AMOUNT_PAID);
             $total_amount_paid = $tps_records[$i]->getData(TPS_PAYMENT_TOTAL_AMOUNT_PAID);
             $tps_due_date = $tps_records[$i]->getData(TPS_PAYMENT_DUE_DATE);
             $tps_synch_date = $tps_records[$i]->getData(TPS_PAYMENT_SYNCH_UPDATE);
             if ($tps_synch_date == date("Y-m-d")) {
                 // skip those whose interest/surcharges have been updated...
                 continue;
             }
             $clsTaxFee = new EBPLTaxFeeSysRef($this->m_dbLink, false);
             // ---- RETRIEVE TAX/FEE DATA
             $clsTaxFeePayable = $clsTaxFee->loadTaxFee($tax_fee_code);
             $clsTaxFeeSurcharge = $clsTaxFee->loadTaxFee($clsTaxFeePayable->getData(EBPLS_SURCHARGE_TAX_FEE_CODE));
             $clsTaxFeeInterest = $clsTaxFee->loadTaxFee($clsTaxFeePayable->getData(EBPLS_INTEREST_TAX_FEE_CODE));
             if ($clsTaxFeePayable == -1 || $clsTaxFeeSurcharge == -1 || $clsTaxFeeInterest == -1) {
                 $this->debug("Unable to load tax fee code {$tax_fee_code}," . $clsTaxFeePayable->getData(EBPLS_SURCHARGE_TAX_FEE_CODE) . "," . $clsTaxFeePayable->getData(EBPLS_INTEREST_TAX_FEE_CODE));
                 $this->setError(-1, "Unable to load tax fee code {$tax_fee_code}," . $clsTaxFeePayable->getData(EBPLS_SURCHARGE_TAX_FEE_CODE) . "," . $clsTaxFeePayable->getData(EBPLS_INTEREST_TAX_FEE_CODE));
                 return -1;
             }
             // retrieve account codes
             $tax_fee_account_code = $clsTaxFeePayable->getData(EBPLS_TAX_ACCOUNT_CODE);
             $surcharge_account_code = $clsTaxFeeSurcharge->getData(EBPLS_TAX_ACCOUNT_CODE);
             $interest_account_code = $clsTaxFeeInterest->getData(EBPLS_TAX_ACCOUNT_CODE);
             // ---- LOAD FORMULA
             //$clsTaxFeePayableFormula = $clsTaxFeePayable->getData(EBPLS_TAX_FORMULA); // we dont need this, used on setting of payment mode only
             $clsTaxFeeSurchargeFormula = $clsTaxFeeSurcharge->getData(EBPLS_TAX_FORMULA);
             $clsTaxFeeInterestFormula = $clsTaxFeeInterest->getData(EBPLS_TAX_FORMULA);
             // ---- COMPUTE BALANCE
             // formula = ( Total Amount Due = (Payable Amount - Paid Amount) + ( Surcharge - Surcharge Paid ) + ( Interest - Interest Paid ) - ( Total Paid Amount )
             // compute raw tax mount due less the raw tax amount paid
             $raw_tax_difference = $tps_amount_due - $tps_amount_paid;
             $total_amount_due = $raw_tax_difference;
             $this->debug("COMPUTE BALANCE : {$raw_tax_difference} = ( {$tps_amount_due} - {$tps_amount_paid} )");
             // compute penalty incurred not yet paid on previous payment
             $penalty_tax_difference = $tps_penalty_amount - $tps_penalty_amount_paid;
             $total_amount_due += $penalty_tax_difference;
             $this->debug("COMPUTE PENALTY : {$penalty_tax_difference} = ( {$tps_penalty_amount} - {$tps_penalty_amount_paid} )");
             // compute interest incurred not yet paid on previous payment
             $interest_tax_difference = $tps_interest_amount - $tps_interest_amount_paid;
             $total_amount_due += $interest_tax_difference;
             $this->debug("COMPUTE INTEREST : {$interest_tax_difference} = ( {$tps_interest_amount} - {$tps_interest_amount_paid} )");
             // compute total balance payable
             // this will be used to calculate interest/surcharge, since these items requires balance amount
             $total_amount_payable = $total_amount_due - $total_amount_paid;
             //$this->debug("COMPUTE TOTAL : $total_amount_payable = $total_amount_due - $total_amount_paid");
             // --------------------------------------------------------------------------
             // ---- COMPUTE SURCHARGE / INTEREST
             $surcharge_amount = $clsTaxFeeSurchargeFormula->computeSurcharge($total_amount_payable, $tps_due_date);
             $interest_amount = $clsTaxFeeSurchargeFormula->computeSurcharge($total_amount_payable, $tps_due_date);
             $this->debug("SURCHARGE {$surcharge_amount}, INTEREST {$interest_amount}");
             // add interest / surcharge to current taxes surcharge/interest balance amount
             $tps_penalty_amount += $surcharge_amount;
             $tps_interest_amount += $interest_amount;
             // --------------------------------------------------------------------------
             // ---- UPDATE PAYMENT SCHEDULE RECORD
             unset($tps_records[$i]->data_elems);
             $tps_records[$i]->data_elems[TPS_PAYMENT_AMOUNT_PAID] = $tps_amount_paid;
             $tps_records[$i]->data_elems[TPS_PAYMENT_PENALTY_AMOUNT] = $tps_penalty_amount;
             $tps_records[$i]->data_elems[TPS_PAYMENT_PENALTY_AMOUNT_PAID] = $tps_penalty_amount_paid;
             $tps_records[$i]->data_elems[TPS_PAYMENT_INTEREST_AMOUNT] = $tps_interest_amount;
             $tps_records[$i]->data_elems[TPS_PAYMENT_INTEREST_AMOUNT_PAID] = $tps_interest_amount_paid;
             $tps_records[$i]->data_elems[TPS_PAYMENT_TOTAL_AMOUNT_PAID] = $total_amount_paid;
             $tps_records[$i]->data_elems[TPS_PAYMENT_SYNCH_UPDATE] = date("Y-m-d");
             $retUpdate = $tps_records[$i]->_update($trans_obj, $payment_id, $admin);
             if ($retUpdate <= 0) {
                 // invalid return, do rollback
                 // call rollback
                 $this->debug("Invalid return on _update on updatePaymentSchedules function, return {$retUpdate}!");
                 $this->setError(-1, "Invalid return on _update on updatePaymentSchedules function, return {$retUpdate}!");
                 return -1;
             }
         }
         mysql_query("UNLOCK TABLES", $this->m_dbLink);
         return 1;
     } else {
         //$this->debug("Unable to load transaction payment schedules on updatePaymentSchedules function, return $tps_records!");
         $this->setError(-1, "Unable to load transaction payment schedules on updatePaymentSchedules function, return {$tps_records}!");
         return -1;
     }
 }
 function addCashPayment($trans_obj, $amount, $admin, $bCommit)
 {
     // retrieve payment schedule list which are not yet fully paid
     $clsTPS = new EBPLSTransactionPaymentSchedule($this->m_dbLink, false);
     $tps_records = $clsTPS->listPaymentSchedule($trans_obj->getData(TRANS_ID), TPS_PAYMENT_STATE_UNPAID, TPS_PAYMENT_DUE_DATE, false);
     if (is_array($tps_records)) {
         // check first if payment exceeds the balance (code assumes that payment schedules are update!)
         $tmp_amount_due = $clsTPS->getTotalAmountDue($trans_obj->getData(TRANS_ID));
         if ($tmp_amount_due <= 0) {
             $this->setError(-2, "All tax/fee payables are paid.");
             return -3;
         }
         $this->debug("The current users balance is P" . number_format($tmp_amount_due, 2) . " < {$amount}!");
         if (round($tmp_amount_due, 2) < round($amount, 2)) {
             // return error if payment amount given exceeds balance
             $this->debug("The current users balance is P" . number_format($tmp_amount_due, 2) . ", please indicate specified amount as cash payment.");
             $this->setError(-2, "The current users balance is P" . number_format($tmp_amount_due, 2) . ", please indicate specified amount as cash payment.");
             return -2;
         }
         $tmp_amount = $amount;
         $tmp_tps_included_records = NULL;
         // ----- START TRANSACTION HERE -----
         $or_code = get_next_system_code($this->m_dbLink, CODES_OR_COL);
         $payment_code = get_next_system_code($this->m_dbLink, CODES_PAY_COL);
         $clsAccounts = new EBPLChartOfAccountsSysRef($this->m_dbLink, false);
         $cash_account_code = $clsAccounts->getCashAccountCode();
         if ($cash_account_code < 0) {
             $this->debug("Unable to load cash account code, return {$cash_account_code}!");
             $this->setError(-5, "Unable to load cash account code, return {$cash_account_code}!");
             // roll back
             return -5;
         }
         $this->debug("OR CODE:{$or_code}, CASH ACCT CODE:{$cash_account_code}, PAYMENT:{$amount}");
         unset($this->or_details);
         for ($i = 0; $i < count($tps_records); $i++) {
             // ---- LOAD TRANSACTION RECORD DATA
             $payment_id = $tps_records[$i]->getData(TPS_PAYMENT_ID);
             $fee_id = $tps_records[$i]->getData(TPS_PAYMENT_FEE_ID);
             $tax_fee_code = $tps_records[$i]->getData(TPS_PAYMENT_TAX_FEE_CODE);
             $tps_amount_due = $tps_records[$i]->getData(TPS_PAYMENT_TOTAL_AMOUNT_DUE);
             $tps_amount_paid = $tps_records[$i]->getData(TPS_PAYMENT_AMOUNT_PAID);
             $tps_penalty_amount = $tps_records[$i]->getData(TPS_PAYMENT_PENALTY_AMOUNT);
             $tps_penalty_amount_paid = $tps_records[$i]->getData(TPS_PAYMENT_PENALTY_AMOUNT_PAID);
             $tps_interest_amount = $tps_records[$i]->getData(TPS_PAYMENT_INTEREST_AMOUNT);
             $tps_interest_amount_paid = $tps_records[$i]->getData(TPS_PAYMENT_INTEREST_AMOUNT_PAID);
             $total_amount_paid = $tps_records[$i]->getData(TPS_PAYMENT_TOTAL_AMOUNT_PAID);
             // ---- RETRIEVE TAX/FEE DATA
             $clsTaxFee = new EBPLTaxFeeSysRef($this->m_dbLink, false);
             $clsTaxFeePayable = $clsTaxFee->loadTaxFee($tax_fee_code);
             $clsTaxFeeSurcharge = $clsTaxFee->loadTaxFee($clsTaxFeePayable->getData(EBPLS_SURCHARGE_TAX_FEE_CODE));
             $clsTaxFeeInterest = $clsTaxFee->loadTaxFee($clsTaxFeePayable->getData(EBPLS_INTEREST_TAX_FEE_CODE));
             if ($clsTaxFeePayable == -1 || $clsTaxFeeSurcharge == -1 || $clsTaxFeeInterest == -1) {
                 $this->debug("Unable to load tax fee code {$tax_fee_code}," . $clsTaxFeePayable->getData(EBPLS_SURCHARGE_TAX_FEE_CODE) . "," . $clsTaxFeePayable->getData(EBPLS_INTEREST_TAX_FEE_CODE));
                 $this->setError(-1, "Unable to load tax fee code {$tax_fee_code}," . $clsTaxFeePayable->getData(EBPLS_SURCHARGE_TAX_FEE_CODE) . "," . $clsTaxFeePayable->getData(EBPLS_INTEREST_TAX_FEE_CODE));
                 // roll back
                 return -1;
             }
             // retrieve account codes
             $tax_fee_account_code = $clsTaxFeePayable->getData(EBPLS_TAX_ACCOUNT_CODE);
             $surcharge_account_code = $clsTaxFeeSurcharge->getData(EBPLS_TAX_ACCOUNT_CODE);
             $interest_account_code = $clsTaxFeeInterest->getData(EBPLS_TAX_ACCOUNT_CODE);
             // ---- COMPUTE BALANCE
             // formula = ( Total Amount Due = (Payable Amount - Paid Amount) + ( Surcharge - Surcharge Paid ) + ( Interest - Interest Paid ) - ( Total Paid Amount )
             // compute raw tax mount due less the raw tax amount paid
             $raw_tax_difference = $tps_amount_due - $tps_amount_paid;
             $total_amount_due = $raw_tax_difference;
             $this->debug("COMPUTE BALANCE : {$raw_tax_difference} = ( {$tps_amount_due} - {$tps_amount_paid} )");
             // compute penalty incurred not yet paid on previous payment
             $penalty_tax_difference = $tps_penalty_amount - $tps_penalty_amount_paid;
             $total_amount_due += $penalty_tax_difference;
             $this->debug("COMPUTE PENALTY : {$penalty_tax_difference} = ( {$tps_penalty_amount} - {$tps_penalty_amount_paid} )");
             // compute interest incurred not yet paid on previous payment
             $interest_tax_difference = $tps_interest_amount - $tps_interest_amount_paid;
             $total_amount_due += $interest_tax_difference;
             $this->debug("COMPUTE INTEREST : {$interest_tax_difference} = ( {$tps_interest_amount} - {$tps_interest_amount_paid} )");
             // compute total balance payable
             // this will be used to calculate interest/surcharge, since these items requires balance amount
             $total_amount_payable = $total_amount_due - $total_amount_paid;
             //$this->debug("COMPUTE TOTAL : $total_amount_payable = $total_amount_due - $total_amount_paid");
             // --------------------------------------------------------------------------
             // ---- PROCESS PAYMENT
             // pay balance on raw tax amount
             if ($raw_tax_difference > 0) {
                 if ($amount > $raw_tax_difference) {
                     // deduct cash in hand with the raw tax amount paid
                     $amount -= $raw_tax_difference;
                     $tax_paid_set = $raw_tax_difference;
                     $tps_amount_paid += $raw_tax_difference;
                 } else {
                     // deduct cash in hand with the raw tax amount paid
                     $tps_amount_paid += $amount;
                     $tax_paid_set = $amount;
                     $amount = 0;
                 }
             }
             // pay surcharge
             if ($penalty_tax_difference > 0 && $amount > 0) {
                 if ($amount > $penalty_tax_difference) {
                     // deduct cash in hand with the penalty tax unpaid
                     $amount -= $penalty_tax_difference;
                     $surcharge_paid_set = $penalty_tax_difference;
                     $tps_penalty_amount_paid += $penalty_tax_difference;
                 } else {
                     // add penalty to tps_penalty_amount
                     $tps_penalty_amount_paid += $amount;
                     $surcharge_paid_set = $amount;
                     $amount = 0;
                 }
                 $tps_penalty_amount_paid += $surcharge_paid_set;
             }
             // pay interest
             if ($interest_tax_difference > 0 && $amount > 0) {
                 if ($amount > $interest_tax_difference) {
                     // deduct cash in hand with the penalty tax unpaid
                     $amount -= $interest_tax_difference;
                     $interest_paid_set = $interest_tax_difference;
                     $tps_interest_amount_paid += $interest_tax_difference;
                 } else {
                     // add interest to tps_interest_amount
                     $tps_interest_amount_paid += $amount;
                     $interest_paid_set = $amount;
                     $amount = 0;
                 }
             }
             // --------------------------------------------------------------------------
             // ---- UPDATE PAYMENT SCHEDULE RECORD
             unset($tps_records[$i]->data_elems);
             $tps_records[$i]->data_elems[TPS_PAYMENT_AMOUNT_PAID] = $tps_amount_paid;
             $tps_records[$i]->data_elems[TPS_PAYMENT_PENALTY_AMOUNT_PAID] = $tps_penalty_amount_paid;
             $tps_records[$i]->data_elems[TPS_PAYMENT_INTEREST_AMOUNT_PAID] = $tps_interest_amount_paid;
             $tps_records[$i]->data_elems[TPS_PAYMENT_TOTAL_AMOUNT_PAID] = $tps_amount_paid + $tps_penalty_amount_paid + $tps_interest_amount_paid;
             $tps_records[$i]->data_elems[TPS_PAYMENT_LAST_UPDATED_BY] = $admin;
             $tps_records[$i]->data_elems[TPS_PAYMENT_LAST_UPDATE_TS] = date("Y-m-d H:i:s");
             $this->debug("{$tps_amount_paid} == {$tps_amount_due} && {$tps_penalty_amount} == {$tps_penalty_amount_paid} && {$tps_interest_amount} == {$tps_interest_amount_paid} ");
             if ($tps_amount_paid == $tps_amount_due && $tps_penalty_amount == $tps_penalty_amount_paid && $tps_interest_amount == $tps_interest_amount_paid) {
                 $tps_records[$i]->data_elems[TPS_PAYMENT_STATUS] = TPS_PAYMENT_STATE_PAID;
                 $tps_records[$i]->data_elems[TPS_PAYMENT_DATE] = date("Y-m-d H:i:s");
             }
             if ($bCommit) {
                 $retUpdate = $tps_records[$i]->_update($trans_obj, $payment_id, $admin);
             } else {
                 $retUpdate = 1;
             }
             if ($retUpdate > 0) {
                 $this->debug("Adding OR Details [tps={$tax_paid_set},sps={$surcharge_paid_set},ips={$interest_paid_set}]");
                 if ($tax_paid_set > 0) {
                     $ret1 = $this->addORDetails($or_code, $trans_obj->getData(TRANS_ID), $payment_id, $fee_id, $tax_fee_code, $cash_account_code, $tax_fee_account_code, $tax_paid_set, "CASH", $bCommit);
                     if ($ret1 < 0) {
                         $this->setError(-1, "error on execute of addORDetails params( {$or_code}, " . $trans_obj->getData(TRANS_ID) . ", {$payment_id}, {$fee_id}, {$tax_fee_code}, {$cash_account_code}, {$tax_fee_account_code}, {$tax_paid_set}, CASH, {$bCommit} )!");
                         // roll back here
                         return -1;
                     }
                 } else {
                     $ret2 = 1;
                 }
                 if ($surcharge_paid_set > 0) {
                     $ret2 = $this->addORDetails($or_code, $trans_obj->getData(TRANS_ID), $payment_id, $fee_id, $tax_fee_code, $cash_account_code, $interest_account_code, $surcharge_paid_set, "SURCHARGE", $bCommit);
                     if ($ret2 < 0) {
                         $this->setError(-2, "error on execute of addORDetails params( {$or_code}, " . $trans_obj->getData(TRANS_ID) . ", {$payment_id}, {$fee_id}, {$tax_fee_code}, {$cash_account_code}, {$interest_account_code}, {$surcharge_paid_set}, SURCHARGE, {$bCommit} )!");
                         // roll back here
                         return -2;
                     }
                 } else {
                     $ret2 = 1;
                 }
                 if ($interest_paid_set > 0) {
                     $ret3 = $this->addORDetails($or_code, $trans_obj->getData(TRANS_ID), $payment_id, $fee_id, $tax_fee_code, $cash_account_code, $surcharge_account_code, $interest_paid_set, "INTEREST", $bCommit);
                     if ($ret3 < 0) {
                         $this->setError(-3, "error on execute of addORDetails params( {$or_code}, " . $trans_obj->getData(TRANS_ID) . ", {$payment_id}, {$fee_id}, {$tax_fee_code}, {$cash_account_code}, {$surcharge_account_code}, {$interest_paid_set}, INTEREST, {$bCommit} )!");
                         // roll back here
                         return -3;
                     }
                 } else {
                     $ret3 = 1;
                 }
                 $this->debug("Adding OR Details [r1={$ret1},r2={$ret2},r3={$ret3}]");
             }
             if ($amount <= 0) {
                 $this->debug("Payment done!");
                 break;
             }
         }
         $this->debug("CREATE OR Payment done LEFT = {$amount}!");
         if ($bCommit) {
             $retCreateOR = $this->create($or_code, $payment_code, $trans_obj->getData(TRANS_ID), $tmp_amount, $bCommit);
             if ($retCreateOR < 0) {
                 // roll back here
                 $this->debug("Error on create of OR header, return {$retCreateOR}!");
                 $this->setError(-6, "Error on create of OR header, return {$retCreateOR}!");
                 return -6;
             }
             $ret_or_code = update_system_code($this->m_dbLink, CODES_OR_COL, $or_code);
             $ret_payment_code = update_system_code($this->m_dbLink, CODES_PAY_COL, $payment_code);
             $tmp_amount_due = $clsTPS->getTotalAmountDue($trans_obj->getData(TRANS_ID));
             if ($tmp_amount_due > 0) {
                 $trans_obj->_setTransPaymentStatusINTERNAL($payment_code, $amount, 'PARTIAL', $admin);
             } else {
                 $trans_obj->_setTransPaymentStatusINTERNAL($payment_code, $amount, 'PAID', $admin);
             }
         }
         // commit here
         return 1;
     } else {
         $this->setError(-1, "All payables have been paid.");
         return -1;
     }
 }