<?php
/**********************************************************************
***********************************************************************/
include_once($path_to_root . "/includes/date_functions.inc");
include_once($path_to_root . "/payroll/includes/db/payroll_run_db.inc");
include_once($path_to_root . "/payroll/includes/payroll_calculation.inc");
include_once($path_to_root . "/gl/includes/add_journal.inc");
include_once($path_to_root . "/includes/ui/items_cart.inc");
include_once($path_to_root . "/payroll/includes/db/loans_db.inc");

//$pcs = "";

function process_payroll($payroll_run_id)
{
    $payroll_run = get_payroll_run_details($payroll_run_id);
    
    $last_completed_employee_code = get_last_completed_emloyee($payroll_run_id);
    $employee_code = get_next_calculated_emloyee($last_completed_employee_code, $payroll_run_id);
    if($employee_code == ""){
        return array("passed" => false, "message" => _("No next payroll employee found. Could not run payroll calculation"));
    }
    
    update_payroll_run_status($payroll_run_id, "P", true, false, true); // Processing
    
    $error_no = 1;
    
    while (strlen($employee_code) > 0)
    { 
        $result = select_calculated_payroll_run_records($payroll_run_id, $employee_code);
        while ($myrow = db_fetch($result))
        {
            $process_type = $myrow['process_type'];
            $component_id = $myrow['component_id'];
            $component = $myrow['component'];
            
            $error_no = 1;
            
            switch ($process_type){
                case 'EMPLOYEE_ALLOWANCES_OVER_USAGE':
                    apply_calculated_employee_allowances_over_usages($employee_code, $payroll_run_id, $component);
                    break;
                case 'ATTENDANCE_ALLOWANCES':
                    apply_calcualted_attendance_summary_values($employee_code, $payroll_run_id, $component);
                    break;
                case 'WORKTIME_DEFICITS':
                    apply_calcualted_worktime_deficit_summary_deductions($employee_code, $payroll_run_id, $component);
                    break;
                case 'PERFORMANCE_RATE_INCENTIVES';
                    apply_calculated_performance_incentive_value($employee_code, $payroll_run_id, $component);
                    break;
                case 'PERFORMANCE_VALUE_INCENTIVES';
                    apply_calculated_performance_incentive_value($employee_code, $payroll_run_id, $component);
                    break;
                case 'MOBILE_ALLOWANCES_OVER_USAGE';
                    apply_calculated_mobile_allowances_over_usages($employee_code, $payroll_run_id, $component);
                    break;
                case 'SALARY_ADVANCES':
                    apply_calculated_salary_advances($component_id, $employee_code, $payroll_run_id);
                    break;
                case 'SALARY_DEDUCTIONS':
                    apply_calculated_salary_deductions($component_id, $employee_code, $payroll_run_id);
                    break;
                case 'SALARY_ADDITIONS':
                    apply_calculated_salary_additions($component_id, $employee_code, $payroll_run_id);
                    break;
                case 'COMMON_PAYROLL_PROCESSES':
                    switch ($component){
                        case 'LOAN_INSTALLMENTS':
                            apply_calculated_loan_installments($employee_code, $payroll_run_id);
                            break;
                        case 'NO_PAY_DEDUCTIONS':
                            apply_calculated_nopay_deductions($employee_code, $payroll_run_id);
                            break;
                        case 'OT_CALCULATIONS':
                            apply_calculated_ot_amounts($employee_code, $payroll_run_id);
                            break;
                        case 'GET_OT_PAYMENTS':
                            apply_paid_ot_amounts($employee_code, $payroll_run_id);
                            break;
                        
                        default:
                    }
                default:
            }
            $error_no = 0;
        }
        $last_completed_employee_code = $employee_code;
        update_last_calculated_employee_code($last_completed_employee_code, $payroll_run_id);
        $employee_code = get_next_calculated_emloyee($last_completed_employee_code, $payroll_run_id);
    }
    
    update_last_calculated_employee_code("", $payroll_run_id);
    
    //generate_account_entries($payroll_run_id, $payroll_run['tran_date']);
    
    if($error_no == 0){
        update_payroll_run_status($payroll_run_id, "R", false, true, false); // Processed
    }
    else{
        update_payroll_run_status($payroll_run_id, "T", false, true, false); // Stopped
    }

}

function generate_account_entries($payroll_run_id, $tran_date)
{
        global $Refs;
        
        
    
        $result = select_payroll_run_summary_accounts($payroll_run_id);

        begin_transaction();
        
        while ($myrow = db_fetch($result))
        {
            if($myrow['debit_code'] == null || $myrow['debit_code'] == "" || 
                    $myrow['credit_code'] == null || $myrow['credit_code'] == ""){
                
                continue;
            }
            $cart = "";
            $data = "";
            
            $amount = abs($myrow['value']);

            $debit['code_id'] = $myrow['debit_code'];
            $credit['code_id'] = $myrow['credit_code']; 
            
            $debit['amount_debit'] = $amount;
            $debit['amount_credit'] = "0.00";
                
            $credit['amount_debit'] = "0.00";
            $credit['amount_credit'] = $amount;
                
            $debit['dimension_id'] = "0";
            $debit['dimension2_id'] = "0";
            $debit['LineMemo'] = "";
    
            $data['items'][] = $debit;
            
            $credit['dimension_id'] = "0";
            $credit['dimension2_id'] = "0";
            $credit['LineMemo'] = "";

            $data['items'][] = $credit;    
            
            $data['trans_type'] = ST_PAYROLL;
            $data['order_date'] = sql2date($tran_date);
            
            $data['comment'] = "Payroll run id $payroll_run_id - ".$myrow['process_name']."[".$myrow['component']."]";
    
            
            $journal_check_result = journal_check($data, $cart);
            if($journal_check_result["passed"] == false){
                return $journal_check_result;
            }
            
            $cart->order_id = $payroll_run_id;
            $journal_add_result = journal_add($cart);
            if($journal_add_result["passed"] === true){
                $journal_id = db_insert_id();
                upadte_payroll_component_summary_record($myrow['prd_id'], $journal_id);
            }
            else{
                cancel_transaction();
                return $journal_add_result;
            }            
        }
        
        $Refs->save(ST_PAYROLL, $payroll_run_id, $payroll_run_id);
        
        add_comments(ST_PAYROLL, $payroll_run_id, sql2date($tran_date), "Payroll run #".$payroll_run_id);
        
        add_audit_trail(ST_PAYROLL, $payroll_run_id, sql2date($tran_date));
        
        commit_transaction();
}


function get_next_calculated_emloyee($last_employee_code, $payroll_run_id)
{
    $my_row = select_next_calculated_emloyee($last_employee_code, $payroll_run_id);
    if($my_row == null){
        return "";
    }
    return $my_row['employee_code'];
}

function apply_calculated_performance_incentive_value($employee_code, $payroll_run_id, $component){
    
    $transaction_cancelled = 0;
    
    $result = select_calculated_performances_incentive_value($employee_code, $payroll_run_id, $component, 'L');
    while ($myrow = db_fetch($result))
    {        
        begin_transaction();
        $num_affected_rows = update_processed_performance_incentive_value($myrow["id"]);
        if($num_affected_rows != 1){
            $transaction_cancelled = 1;
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_mobile_allowances_over_usage");
        }
        else{
            commit_transaction();
        }
        
        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}


function apply_calculated_mobile_allowances_over_usages($employee_code, $payroll_run_id, $component){
    
    $transaction_cancelled = 0;
    
    $result = select_calculated_mobile_allowances_over_usages($employee_code, $payroll_run_id, $component, 'L');
    while ($myrow = db_fetch($result))
    {        
        begin_transaction();
        $num_affected_rows = update_processed_mobile_allowances_over_usage($myrow["id"]);
        if($num_affected_rows != 1){
            $transaction_cancelled = 1;
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_mobile_allowances_over_usage");
        }
        else{
            commit_transaction();
        }
        
        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}


function apply_calculated_employee_allowances_over_usages($employee_code, $payroll_run_id, $component){
    
    $transaction_cancelled = 0;
    
    $result = select_calculated_employee_allowances_over_usages($employee_code, $payroll_run_id, $component, 'L');
    while ($myrow = db_fetch($result))
    {        
        begin_transaction();
        $num_affected_rows = update_processed_employee_allowances_over_usage($myrow["id"]);
        if($num_affected_rows != 1){
            $transaction_cancelled = 1;
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_employee_allowances_over_usage");
        }
        else{
            commit_transaction();
        }
        
        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}


function apply_calculated_salary_additions($process_id, $employee_code, $payroll_run_id){
    
    $transaction_cancelled = 1;
    
    $result = select_calculated_salary_additions($process_id, $employee_code, $payroll_run_id, 'L');
    while ($myrow = db_fetch($result))
    {
        $salary_addition = $myrow["salary_addition"];
        
        begin_transaction();
        $num_affected_rows = update_processed_salary_addition($myrow["id"], $payroll_run_id);
        if($num_affected_rows != 1){
            $transaction_cancelled = 1;
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_salary_addition");
        }   
        else{
            commit_transaction();
            $transaction_cancelled = 0;
        }

        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}


function apply_calculated_salary_advances($process_id, $employee_code, $payroll_run_id){
    
    $transaction_cancelled = 1;
    
    $result = select_calculated_salary_advances($process_id, $employee_code, $payroll_run_id, 'L');
    while ($myrow = db_fetch($result))
    {
        $salary_advance = $myrow["salary_advance"];
        
        begin_transaction();
        $num_affected_rows = update_processed_salary_advance($myrow["id"], $payroll_run_id);
        if($num_affected_rows != 1){
            $transaction_cancelled = 1;
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_salary_advances");
        }   
        else{
            commit_transaction();
            $transaction_cancelled = 0;
        }

        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}





function apply_calculated_salary_deductions($process_id, $employee_code, $payroll_run_id){
    
    $transaction_cancelled = 1;
    
    $result = select_calculated_salary_deductions($process_id, $employee_code, $payroll_run_id, 'L');
    while ($myrow = db_fetch($result))
    {
        $salary_deduction = $myrow["salary_deduction"];
        
        begin_transaction();
        $num_affected_rows = update_processed_salary_deduction($myrow["id"], $payroll_run_id);
        if($num_affected_rows != 1){
            $transaction_cancelled = 1;
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_salary_deduction");
        }   
        else{
            commit_transaction();
            $transaction_cancelled = 0;
        }

        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}


function apply_calculated_loan_installments($employee_code, $payroll_run_id){
    
    $transaction_cancelled = 0;
    
    $result = select_calculated_loan_installments($employee_code, $payroll_run_id, 'L');
    while ($myrow = db_fetch($result))
    {
        $loan_details = get_loan_details($myrow['loan_id']);
        $total_loan_payment = get_loan_total_paid_amount($myrow['loan_id']);
        
        $completed = 0;
        $total_paid = (double)$total_loan_payment["total_paid"];
        $loan_amount = (double)$loan_details["loan_amount"];
        
        if($total_paid >= $loan_amount){
            //Loan has been fully paid before processing this calculation; may be by any other parallel payroll.
            return false;
        }
        
        $this_installment = (double)$myrow["installment_amount"];
        
        $total_paid += $this_installment;
        
        if($total_paid >= $loan_amount){
            $completed = 1;    
        }
        
        begin_transaction();
        $num_affected_rows = update_processed_loan_installment($myrow["id"]);
        if($num_affected_rows != 1){
            $transaction_cancelled = 1;
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_loan_installment");
        }
        else{
            if($completed == 1){
                update_processed_loan($myrow['loan_id'], $completed);
            }
            commit_transaction();
        }
        
        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}

function apply_calculated_nopay_deductions($employee_code, $payroll_run_id){
    
    $transaction_cancelled = 1;
    
    $result = select_calculated_nopay_deductions($employee_code, $payroll_run_id, 'L');
    while ($myrow = db_fetch($result))
    {
        $nopay_days = $myrow["nopay_days"];
        $nopay_amount = $myrow["nopay_amount"];
        
        begin_transaction();
        $num_affected_rows = update_processed_nopay_deduction($myrow["id"], $nopay_amount, $payroll_run_id);
        if($num_affected_rows != 1){
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_nopay_deduction");
        }   
        else{
            $num_affected_rows = update_processed_leave_entitlement( $myrow["leave_entitlement_id"], $nopay_days, $payroll_run_id);
            if($num_affected_rows == 1){
                commit_transaction();
                $transaction_cancelled = 0;
            }
            else{
                cancel_transaction();
                insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "db_insert_id is not > 1 in insert_nopay_deduction");
            }
        }
        
        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}

function apply_calcualted_worktime_deficit_summary_deductions($employee_code, $payroll_run_id, $component){
    
    $transaction_cancelled = 1;

    $result = select_calculated_worktime_deficit_summary_deductions($employee_code, $payroll_run_id, $component,"L");
    while ($myrow = db_fetch($result))
    {  
        begin_transaction();
        $num_affected_rows = update_processed_worktime_deficit_summary_deduction($myrow["id"]);
        if($num_affected_rows != 1){
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_worktime_deficit_summary_deduction");
        } 
        else{
            commit_transaction();
            $transaction_cancelled = 0;
        }
        
        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}




function apply_calcualted_attendance_summary_values($employee_code, $payroll_run_id, $component){
    
    $transaction_cancelled = 1;

    $result = select_calcualted_attendance_summary_values($employee_code, $payroll_run_id, $component,"L");
    while ($myrow = db_fetch($result))
    {  
        begin_transaction();
        $num_affected_rows = update_processed_attendance_summary_value($myrow["id"]);
        if($num_affected_rows != 1){
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_attendance_summary_value");
        } 
        else{
            commit_transaction();
            $transaction_cancelled = 0;
        }
        
        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}


function apply_calculated_ot_amounts($employee_code, $payroll_run_id){
    
    $transaction_cancelled = 1;
    
    $result = select_calculated_ot_amounts($employee_code, $payroll_run_id, "'L'");
    while ($myrow = db_fetch($result))
    {  
        begin_transaction();
        $num_affected_rows = update_processed_ot_amounts($myrow["id"], $payroll_run_id);
        if($num_affected_rows != 1){
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_ot_amounts");
        } 
        else{
            commit_transaction();
            $transaction_cancelled = 0;
        }
        
        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}


function apply_paid_ot_amounts($employee_code, $payroll_run_id){
    
    $transaction_cancelled = 1;
    
    $result = select_paid_ot_amounts($employee_code, $payroll_run_id, 'S');
    while ($myrow = db_fetch($result))
    {  
        begin_transaction();
        $num_affected_rows = update_paid_ot_amounts($myrow["id"], $payroll_run_id);
        if($num_affected_rows != 1){
            cancel_transaction();  
            insert_payroll_log_message($payroll_run_id,1,$myrow["id"], "num_affected_rows is not 1 in update_processed_ot_amounts");
        } 
        else{
            commit_transaction();
            $transaction_cancelled = 0;
        }
        
        if($transaction_cancelled != 0){
            return false;
        }
    }
    
    return true;

}


?>
