<?php
/**
 * CodeIgniter library
 *
 * @category CodeIgniter
 * @license /_licenses/untermStrich/agb_normal.pdf
 * @author Christian Wengg
 * @copyright 2009 untermStrich
 * @package us_libraries
 * @version $Id$
*/

if (!defined('BASEPATH')) { exit('No direct script access allowed'); }

require_once APPPATH.'us_libraries/Value_object_addi.php';

/**
 * Used to save a fee
 *
 * @property    My_Controller           $CI                     The main CI object
 */
class Fees_values extends Value_object_addi
{
    protected $add_or_id;
    protected $project_id;
    protected $is_invoiced;
    protected $is_transfered;
    protected $del_after_transfer;
    protected $purpose;
    protected $fee_no;
    protected $fee_date;
    protected $address_id;
    protected $cost_centre_id;
    protected $fee_category_id;
    protected $value;
    protected $turnover_rate;
    protected $due_date;
    protected $fee_account_id;
    protected $is_done;
    protected $done_date;
    protected $deduction;
    protected $remited;
    protected $remit_purpose;
    protected $remited_is_withholded;
    protected $reminder_level;
    protected $last_reminder_date;
    protected $is_percentage;
    protected $predecessor_id = 0;
    protected $successor_id = 0;
    protected $correspondence_id;
    protected $is_calcexp = null;
    protected $e_invoice_json = null;
    
    protected $currency_id;
    protected $exchange_rate;
    
    protected $sdd_done_date;
    protected $sdd_due_date;
    protected $sdd_is_percentage;
    protected $sdd_remited;
    protected $sdd_deduction;
    protected $sdd_remit_purpose;
    protected $sdd_exchange_rate;
    
    protected $retention_type = null;
    protected $retention_date = null;
    protected $retention = null;

    protected $from_date;
    protected $to_date;
    
    protected $change_project_within_chain = false;
    protected $finally_invoiced;
    protected $wp_allocation_vars;
    protected $wp_sddallocation_vars;
    
    /**
     * Init the fees values from $_POST
     *
     * @return  object  An Fees_values object with all values out of the post array
     */
    public static function init_from_post()
    {
        $obj = new Fees_values();
        $obj->CI = CI_Controller::get_instance();
        
        $obj->CI->load->model('System_settings_model', 'system_settings');

        $obj->add_or_id = $obj->CI->input->post('fees_edit');
        $obj->is_invoiced = $obj->CI->input->post('fees_is_invoiced');
        $obj->is_transfered = (boolean) $obj->CI->input->post('fees_is_transfered');
        $obj->del_after_transfer = (boolean) $obj->CI->input->post('fees_del_after_transfer');
        $obj->project_id = $obj->CI->input->post('fees_project');
        $obj->purpose = $obj->CI->input->post('fees_purpose');
        $obj->fee_no = trim($obj->CI->input->post('fees_fee_no'));
        $obj->fee_date = new UsDate($obj->CI->input->post('fees_fee_date'), null, true, null);
        $obj->address_id = $obj->CI->input->post('fees_address');
        $obj->cost_centre_id = $obj->CI->input->post('fees_cost_centre_name');
        $obj->fee_category_id = $obj->CI->input->post('fees_fee_category_name');
        $obj->value = $obj->CI->input->post('fees_value');
        $turnover_rate = usnumber_to_float($obj->CI->input->post('fees_turnover_rate'))/100;
        $obj->turnover_rate = float_to_usnumber($turnover_rate);
        $obj->due_date = new UsDate($obj->CI->input->post('fees_due_date'), null, true, null);
        $obj->fee_account_id = $obj->CI->input->post('fees_fee_account_name');
        $obj->is_done = (boolean) $obj->CI->input->post('fees_is_done');
        $obj->done_date = new UsDate($obj->CI->input->post('fees_done_date'), null, true, null);
        $obj->deduction = $obj->CI->input->post('fees_deduction');
        $obj->is_percentage = (boolean) $obj->CI->input->post('fees_is_percentage');
        $obj->remited = $obj->CI->input->post('fees_remited');
        $obj->remit_purpose = $obj->CI->input->post('fees_remit_purpose');
        $obj->remited_is_withholded = $obj->CI->input->post('fees_remited_is_withholded');
        $obj->reminder_level = $obj->CI->input->post('fees_reminder_level');
        $obj->last_reminder_date = new UsDate($obj->CI->input->post('fees_last_reminder_date'), null, true, null);
        $obj->correspondence_id = $obj->CI->input->post('fees_correspondence_id');
        $obj->is_calcexp = intval($obj->CI->input->post('fees_is_calcexp'));
        $obj->addi_vars = $obj->CI->fees->get_addi_vars_post();
        $obj->fee_allocation_vars = $obj->_get_fee_allocation_vars_post();
        $obj->wp_allocation_vars = $obj->_get_wp_allocation_vars_post();
        
        $obj->e_invoice_json = null;
        
        $obj->currency_id = null;
        $obj->exchange_rate = null;
        if ($obj->CI->system_settings->getboolProject_use_currency()) {
            $obj->currency_id = $obj->CI->input->post('fees_currency_id');
            $obj->exchange_rate = $obj->CI->input->post('fees_exchange_rate');
            
            if (empty($obj->currency_id)) {
                $obj->currency_id = $obj->CI->system_settings->getGlobal_currency();
            }
            if (empty($obj->exchange_rate)) {
                $obj->exchange_rate = 1;
            }
        }

        $obj->from_date = new UsDate($obj->CI->input->post('fees_from_date'), null, true, null);
        $obj->to_date = new UsDate($obj->CI->input->post('fees_to_date'), null, true, null);
        
        $obj->sdd_done_date = new UsDate($obj->CI->input->post('sdd_done_date'), null, true, null);
        $obj->sdd_due_date = new UsDate($obj->CI->input->post('sdd_due_date'), null, true, null);
        $obj->sdd_is_percentage = (boolean) $obj->CI->input->post('sdd_is_percentage');
        $obj->sdd_remited = $obj->CI->input->post('sdd_remited');
        $obj->sdd_deduction = $obj->CI->input->post('sdd_deduction');
        $obj->sdd_remit_purpose = $obj->CI->input->post('sdd_remit_purpose');
        $obj->sdd_exchange_rate = $obj->CI->input->post('sdd_exchange_rate');
        
        $obj->change_project_within_chain = (boolean) $obj->CI->input->post('fees_change_project_within_chain');
        $obj->finally_invoiced = $obj->CI->input->post('fees_finally_invoiced') ? true : false;
        
        $obj->wp_sddallocation_vars = $obj->_get_wp_allocation_vars_post(true);
        return $obj;
    }

     /**
     * Init an Fees_values object with all values from a given stdClass object
     *
     * @param   object  $values                     stdClass object with fee values to initialize a valid Fees_values object out of it
     * @param   boolean $not_override_wp_parents    Optional Do not overwrite the parent of work packages within _get_wp_allocation_vars
     * @return  object  An Fees_values object with all values out of the given stdClass object
     */
    public static function init_from_values(stdClass $values, $not_override_wp_parents=false)
    {
        $obj = new Fees_values();
        $obj->CI = CI_Controller::get_instance();
        
        if (!isset($values->allocations)) {
            $values->allocations = array();
        }
        if (!isset($values->fee_wps)) {
            $values->fee_wps = array();
        }

        if(isset($values->sdd_done_date)) {
            $obj->sdd_done_date = $values->sdd_done_date;
            $obj->sdd_due_date = $values->sdd_due_date;
            $obj->sdd_is_percentage = (boolean) $values->sdd_is_percentage;
            $obj->sdd_remited = float_to_usnumber($values->sdd_remited);
            $obj->sdd_deduction = float_to_usnumber($values->sdd_deduction);
            $obj->sdd_remit_purpose = $values->sdd_remit_purpose;
            $obj->remited_is_withholded = !empty($values->remited_is_withholded);
            $obj->sdd_exchange_rate = (isset($values->sdd_exchange_rate)) ? float_to_usnumber($values->sdd_exchange_rate) : 1;
            $obj->fee_allocation_vars = array();
            $obj->wp_sddallocation_vars = $obj->_get_wp_allocation_vars($values->allocations, $values->fee_wps, true, $not_override_wp_parents);
        } else {
            $obj->add_or_id = $values->id;
            $obj->is_invoiced = $values->is_invoiced;
            $obj->is_transfered = (boolean) $values->is_transfered;
            $obj->del_after_transfer = (isset($values->del_after_transfer))? (boolean) $values->del_after_transfer : false;
            $obj->project_id = $values->project_id;
            $obj->purpose = $values->purpose;
            $obj->fee_no = $values->fee_no;
            $obj->fee_date = $values->fee_date;
            $obj->address_id = $values->address_id;
            $obj->cost_centre_id = $values->cost_centre_id;
            if (isset($values->fee_category_id)) {
                $obj->fee_category_id = $values->fee_category_id;
            } else {
                $obj->fee_category_id = null;
            }
            $obj->value = float_to_usnumber($values->value);
            $obj->turnover_rate = float_to_usnumber($values->turnover_rate);
            $obj->due_date = $values->due_date;
            $obj->fee_account_id = $values->fee_account_id;
            $obj->is_done = $values->is_done;
            $obj->done_date = $values->done_date;
            $obj->deduction = float_to_usnumber($values->deduction);
            $obj->is_percentage = $values->is_percentage;
            $obj->remited = float_to_usnumber($values->remited);
            $obj->remit_purpose = $values->remit_purpose;
            $obj->remited_is_withholded = !empty($values->remited_is_withholded);
            $obj->reminder_level = $values->reminder_level;
            $obj->last_reminder_date = $values->last_reminder_date;
            $obj->predecessor_id = $values->predecessor_id;
            $obj->successor_id = $values->successor_id;
                        
            $obj->currency_id = null;
            if (isset($values->currency_id)) {
                $obj->currency_id = $values->currency_id;
            }
            $obj->exchange_rate = null;
            if (isset($values->exchange_rate)) {
                $obj->exchange_rate = float_to_usnumber($values->exchange_rate);
            }
            
            if (isset($values->finally_invoiced)) {
                $obj->finally_invoiced = (boolean) $values->finally_invoiced;
            } else {
                $obj->finally_invoiced = false;
            }
                        
            if (isset($values->correspondence_id)) {
                $obj->correspondence_id = $values->correspondence_id;
            }
            
            if (isset($values->change_project_within_chain)) {
                $obj->change_project_within_chain = (boolean) $values->change_project_within_chain;
            }
            if (isset($values->is_calcexp)) {
                $obj->is_calcexp = intval($values->is_calcexp);
            } else {
                $obj->is_calcexp = null;
            }
            
            $obj->retention_type = 0;
            if (isset($values->retention_type)) {
                $obj->retention_type = intval($values->retention_type);
            }
            $obj->retention_date = null;
            if (isset($values->retention_date)) {
                $obj->retention_date = $values->retention_date;
            }
            $obj->retention = 0;
            if (isset($values->retention)) {
                $obj->retention = abs(floatval($values->retention));
            }
            if(isset($values->e_invoice_json)){
                $obj->e_invoice_json = $values->e_invoice_json;
            }
            
            $obj->fee_allocation_vars = !empty($values->costs) ? $obj->_get_fee_allocation_vars($values->costs) : array();
            $obj->wp_allocation_vars = $obj->_get_wp_allocation_vars($values->allocations, $values->fee_wps, false, $not_override_wp_parents);

            if (isset($values->from_date)) {
                $obj->from_date = $values->from_date;
            }
            if (isset($values->to_date)) {
                $obj->to_date = $values->to_date;
            }

            if (!isset($values->addi_fields)) {
                $obj->CI->load->model('Fees_model', 'fees');
                $values->addi_fields = $obj->CI->fees->get_addi_list();
            }
            self::init_addi_vars_from_values($obj, $values);
        }
        
        return $obj;
    }

    /**
     * Validate and ensure all values are appropriate
     *
     * @return  mixed   false on success, else the error message
     *
     * @todo    implement!!
     */
    public function validate()
    {
        $a_id = explode(Fees_model::ID_SEPERATOR,$this->add_or_id);
        if ($this->add_or_id!=='add' && (!is_array($a_id)) && count($a_id) != 2) {
            return 'Fee ID has to be "add" or an ID';
        }
        return false;
    }

    /**
     * Set variable remited_is_withholded (true/false)
     */
    public function set_remited_is_withholded($is_withholded)
    {
        $this->remited_is_withholded = boolval($is_withholded);
    }

    /**
     * Get variable remited_is_withholded
     */
    public function get_remited_is_withholded()
    {
        return boolval($this->remited_is_withholded);
    }
    
    /**
     * Get fee to save
     *
     * @return  array
     */
    public function get_fee_to_save()
    {
        $data = array(
            'project_id'                =>  intval($this->project_id),
            'purpose'                   =>  $this->purpose,
            'fee_no'                    =>  $this->fee_no,
            'fee_date'                  =>  $this->fee_date->mysql(),
            'address_id'                =>  intval($this->address_id),
            'cost_centre_id'            =>  intval($this->cost_centre_id),
            'fee_category_id'           =>  intval($this->fee_category_id),
            'turnover_rate'             =>  usnumber_to_float($this->turnover_rate),
            'fee_account_id'            =>  intval($this->fee_account_id),
            'entry_date'                =>  'CURRENT_TIMESTAMP',
            'finally_invoiced'          => $this->finally_invoiced,
            'remited_is_withholded'     => $this->remited_is_withholded
        );

        if(property_exists($this, 'currency_id')) {
            $data['currency_id'] = $this->currency_id;
        }
        if (!empty($this->currency_id) && property_exists($this, 'exchange_rate')) {
            $value_otcurr = usnumber_to_float($this->value);
            $exchange_rate = usnumber_to_float($this->exchange_rate);
            $data['value'] = $value_otcurr*$exchange_rate;
            $data['value_otcurr'] = $value_otcurr;
        } else {
            $data['value'] = usnumber_to_float($this->value);
        }
        
        if ($this->add_or_id === 'add') {
            if ( $this->is_correspondence_fee() ) {
                $a_correspondence_id = explode('__', $this->correspondence_id);
                $corr_id = (count($a_correspondence_id) > 1) ? intval($a_correspondence_id[0]) : intval($this->correspondence_id);
                $data['correspondence_id'] = $corr_id;
            } else {
                $data['correspondence_id'] = null;
            }            
        }

        $data['due_date'] = $this->due_date->mysql();
        if($this->get_invoiced_type() !== Fees_model::TYPE_INVOICED && !$this->is_transfered()){
            $data['due_date_planned'] = $this->due_date->mysql();
        } 

        if ($this->add_or_id==='add'|| $this->is_transfered()) {
            $data['remited'] = 0;
            $data['remit_purpose'] = '';
            $data['predecessor_id'] = intval($this->predecessor_id);
            $data['successor_id'] = intval($this->successor_id);
            $data['reminder_level'] = 0;
        }
        if ($this->is_transfered()){
            $data['predecessor_id'] = 0;
            $data['successor_id'] = 0;
        }
        if (property_exists($this, 'is_calcexp')) {
            $data['is_calcexp'] = boolval($this->is_calcexp);
        }
        if (property_exists($this, 'e_invoice_json')) {
            $data['e_invoice_json'] = $this->e_invoice_json;
        }
        if (property_exists($this, 'from_date')) {
            $data['from_date'] = !empty($this->from_date) ? $this->from_date->mysql() : null;
        }
        if (property_exists($this, 'to_date')) {
            $data['to_date'] = !empty($this->to_date) ? $this->to_date->mysql() : null;
        }
        if (property_exists($this, 'retention_type') && property_exists($this, 'retention') && property_exists($this, 'retention_date')) {
            $data['retention_type'] = intval($this->retention_type);
            $data['retention_date'] = !empty($this->retention_date) && !$this->retention_date->is_null() ? $this->retention_date->mysql() : null;
            $data['retention'] = floatval($this->retention);
        }
        return $data;
    }

    /**
     * Get the fee number
     *
     * @return  string
     */
    public function getFeeNumber()
    {
        return $this->fee_no;
    }
    
    /**
     * Get project ID
     * 
     * @return  integer
     */
    public function get_project_id()
    {
        return intval($this->project_id);
    }
    
    /**
     * Get the invoiced type of the Fee
     *
     * @return  boolean
     */
    public function get_invoiced_type()
    {
        $id = $this->getId();
        if( $id == 'add') {
            $type = $this->is_invoiced;
        } else {
            $a = explode(Fees_model::ID_SEPERATOR, $id);
            if(!is_array($a) || count($a) !== 2){
                basic_error('get_invoiced_type - The id "'.$id.'" cannot be splitted.', null, __CLASS__.'::'.__FUNCTION__);
            }
            $type = $a[1];
        }

        switch ($type) {
            case Fees_model::TYPE_INVOICED:
                return Fees_model::TYPE_INVOICED;
                break;
            case Fees_model::TYPE_NOT_INVOICED:
                return Fees_model::TYPE_NOT_INVOICED;
                break;
            default:
                basic_error('get_invoiced_type - Invoiced Type is invalid!', null, __CLASS__.'::'.__FUNCTION__);
                break;
        }
    }

    /**
     * Get the ID
     *
     * Only valid if self::isNew() === false
     *
     * @return  string      The ID
     */
    public function getId()
    {
        return $this->add_or_id;
    }

    /**
     * Check if the fee should be deleted after transfer
     *
     * @return  boolean
     */
    public function del_after_transfer()
    {
        if( $this->is_transfered() && $this->del_after_transfer === true){
            return true;
        } else {
            return false;
        }
    }

    /**
     * Set the fee as transfered from outside
     *
     * @return  void
     */
    public function set_transfered()
    {
        $this->is_invoiced =Fees_model::TYPE_INVOICED;
    }

    /**
     * Check if the fee is transfered from planned to invoiced
     *
     * @return  boolean
     */
    public function is_transfered()
    {
        $id = $this->getId();
        if( $id !== 'add' && $this->is_transfered === false){
            if($this->is_invoiced != $this->get_invoiced_type() && $this->is_invoiced == Fees_model::TYPE_INVOICED){
                return true;
            }
        }
        return false;
    }

    /**
     * Get fee values to set done an invoiced fee
     *
     * @return  array
     */
    public function get_values_to_set_done()
    {
        $data = array(
            'is_done'                   =>  true,
            'remit_purpose'             =>  $this->sdd_remit_purpose,
            'done_date'                 =>  $this->sdd_done_date->mysql(),
            'is_percentage'             =>  $this->sdd_is_percentage,
            'remited'                   =>  usnumber_to_float($this->sdd_remited),
            'deduction'                 =>  usnumber_to_float($this->sdd_deduction)
        );
        return $data;
    }

    /**
     * Get the new due date of the residue
     *
     * @return  object
     */
    public function get_due_date_residue()
    {
        return $this->sdd_due_date;
    }
    
    /**
     * Get info about changing the project(and work_package_id) also on predecessors and successors
     * 
     * @return boolean
     */
    public function get_change_project_within_chain()
    {
        return $this->change_project_within_chain;
    }
    
    /**
     * Is fee created from correspondence module
     * 
     * Just for fees created in vX
     * 
     * @return  boolean
     */
    public function is_correspondence_fee()
    {
        return ($this->correspondence_id === null || $this->correspondence_id === '') ? false : true;
    }
    
    /**
     * Get exchange rate
     * 
     * @return  float
     */
    public function get_exchange_rate()
    {
        if (!empty($this->exchange_rate)) {
            return usnumber_to_float($this->exchange_rate);
        } else {
            return false;
        }
    }
    
    /**
     * Get set_done exchange rate
     * 
     * @return  float
     */
    public function get_set_done_exchange_rate()
    {
        if (!empty($this->sdd_exchange_rate)) {
            return usnumber_to_float($this->sdd_exchange_rate);
        } else {
            return false;
        }
    }

    /**
     * Get an array with the fee allocation fields values
     *
     * This function loads the value form $_POST
     *
     * @param bool    from_sdd    Check if call comes from the set done dialog
     * 
     * @return  array   Values
     */
    private function _get_fee_allocation_vars_post($from_sdd=false)
    {
        $vars = array();
        $prefix = ($from_sdd) ? '_sdd' : '';

        $post_keys = preg_grep("@^fee_area_".$prefix."_[0-9]+_(offer_id_|quantity_|unit_|price_|costs_view_|supplement_|extras_value_|rebate_value_)[0-9]+@", array_keys($_POST));
        foreach ($post_keys as $key) {
            $cleaned_key = str_replace("fee_area_".$prefix."_", "", $key);
            
            $offer_id_parts = explode("_", $cleaned_key);
            $offer_id = intval($offer_id_parts[0]);
            if(empty($vars[$offer_id])) {
                $vars[$offer_id] = array();
            }
            
            $cleaned_key = str_replace("_".$offer_id."_", "", $cleaned_key);
            $vars[$offer_id][$cleaned_key] = usnumber_to_float($this->CI->input->post($key));
        }

        return $vars;
    }
    
    /**
     * Get an array with the wp allocation fields values
     *
     * This function loads the value form $_POST
     * 
     * @param   bool    from_sdd    Check if call comes from the set done dialog
     *
     * @return  array   Values
     */
    private function _get_wp_allocation_vars_post($from_sdd=false)
    {
        $vars = array();
        $prefix = ($from_sdd) ? '_sdd' : '';
        
        $post_keys = preg_grep("@^fee_wp".$prefix."_[0-9]+@", array_keys($_POST));
        foreach ($post_keys as $key) {
            $vars[$key] = usnumber_to_float($this->CI->input->post($key));
        }

        return $vars;
    }

    /**
     * Get an array with the wp allocation fields values
     *
     * This function loads the value from a given stdClass object
     *
     * @param   object  $allocations                Holds the infos (wp_id, percent, etc)
     * @param   object  $fee_wps                    Holds the whole tree (fee areas)
     * @param   boolean $not_override_wp_parents    Optional Do not overwrite the parent of work packages
     * @return  array   Values
     */
    private function _get_fee_allocation_vars($costs)
    {
        $vars = array();
        foreach ($costs as $offer_id => $wpvalues) {
            if(empty($vars[$offer_id])) {
                $vars[$offer_id] = array();
            }
            
            foreach($wpvalues as $wp_id => $costvalue) {
                if (array_key_exists('offer_id', $costvalue)) {
                    $vars[$offer_id]['offer_id_'.$wp_id] = $costvalue['offer_id'];
                }
                if (array_key_exists('quantity', $costvalue)) {
                    $vars[$offer_id]['quantity_'.$wp_id] = $costvalue['quantity'];
                }
                if (array_key_exists('unit', $costvalue)) {
                    $vars[$offer_id]['unit_'.$wp_id] = $costvalue['unit'];
                }
                if (array_key_exists('price', $costvalue)) {
                    $vars[$offer_id]['price_'.$wp_id] = $costvalue['price'];
                }
                if (array_key_exists('costs', $costvalue)) {
                    $vars[$offer_id]['costs_'.$wp_id] = $costvalue['costs'];
                }
                if (array_key_exists('costs_view', $costvalue)) {
                    $vars[$offer_id]['costs_view_'.$wp_id] = $costvalue['costs_view'];
                }
                if (array_key_exists('supplement', $costvalue)) {
                    $vars[$offer_id]['supplement_'.$wp_id] = $costvalue['supplement'];
                }
                if (array_key_exists('extras_value', $costvalue)) {
                    $vars[$offer_id]['extras_'.$wp_id] = $costvalue['extras_value'];
                }
                if (array_key_exists('rebate_value', $costvalue)) {
                    $vars[$offer_id]['rebate_'.$wp_id] = $costvalue['rebate_value'];
                }
            }
        }
        
        return $vars;
    }
    
    /**
     * Get an array with the wp allocation fields values
     *
     * This function loads the value from a given stdClass object
     * 
     * @param   object  $allocations                Holds the infos (wp_id, percent, etc)
     * @param   object  $fee_wps                    Holds the whole tree (fee areas)
     * @param   boolean $not_override_wp_parents    Optional Do not overwrite the parent of work packages
     * @return  array   Values
     */
    private function _get_wp_allocation_vars($allocations, $fee_wps, $from_sdd=false, $not_override_wp_parents=false)
    {
        $vars = array();
        
        $prefix = ($from_sdd) ? '_sdd' : '';
        
        foreach ($fee_wps as $fee_wp) {
            $vars['fee_wp'.$prefix.'_'.$fee_wp->id.'_quantity'] = 1;
            $vars['fee_wp'.$prefix.'_'.$fee_wp->id.'_quantity_id'] = 0;
            $vars['fee_wp'.$prefix.'_'.$fee_wp->id.'_price'] = 0;
            $vars['fee_wp'.$prefix.'_'.$fee_wp->id] = 0;
            $vars['fee_wp'.$prefix.'_'.$fee_wp->id.'_otcurr'] = 0;
        }
        
        foreach ($allocations as $allocation) {
            $this->CI->work_packages->get_parent($this->get_project_id(), $allocation->work_package_id, $parent_id);
            
            $quantity = 0;
            if (property_exists($allocation, 'currently_billable_quantity')) {
                $quantity = $allocation->currently_billable_quantity;
            } else if (property_exists($allocation, 'quantity')) {
                $quantity = $allocation->quantity;
            }
            $quantity_id = !empty($allocation->quantity_id) ? $allocation->quantity_id : 0;
            
            $value = 0;
            $value_otcurr = 0;
            if (property_exists($allocation, 'old_hoai_currently_billable_value')) {
                $value = $allocation->old_hoai_currently_billable_value;
                $value_otcurr = $allocation->old_hoai_currently_billable_value;
            } else if (property_exists($allocation, 'currently_billable_value_overall_rep')) {
                $value = $allocation->currently_billable_value_overall_rep;
                $value_otcurr = $allocation->currently_billable_value_overall_rep_otcurr;
            } else if (property_exists($allocation, 'value')) {
                $value = $allocation->value;
                $value_otcurr = $allocation->value_otcurr ?? $value;
            }
            
            $price = 0;
            if(!empty($quantity)) {
                $price = $value / $quantity;
            }
            
            $vars['fee_wp'.$prefix.'_'.$allocation->work_package_id.'_quantity'] = $quantity;
            $vars['fee_wp'.$prefix.'_'.$allocation->work_package_id.'_quantity_id'] = $quantity_id;

            if (array_key_exists('fee_wp'.$prefix.'_'.$allocation->work_package_id.'_price', $vars)) {
                $vars['fee_wp'.$prefix.'_'.$allocation->work_package_id.'_price'] += $price;
            }
            if (array_key_exists('fee_wp'.$prefix.'_'.$allocation->work_package_id, $vars)) {
                $vars['fee_wp'.$prefix.'_'.$allocation->work_package_id] += $value;
            }
            if (array_key_exists('fee_wp'.$prefix.'_'.$allocation->work_package_id.'_otcurr', $vars)) {
                $vars['fee_wp'.$prefix.'_'.$allocation->work_package_id.'_otcurr'] += $value_otcurr;
            }
            if ($not_override_wp_parents===true) {
                if (array_key_exists('fee_wp'.$prefix.'_'.$parent_id, $vars)) {
                    $vars['fee_wp'.$prefix.'_'.$parent_id] += $value;
                    if (array_key_exists('fee_wp'.$prefix.'_'.$parent_id.'_otcurr', $vars)) {
                        $vars['fee_wp'.$prefix.'_'.$parent_id.'_otcurr'] += $value_otcurr;
                    }
                }
            }
        }
        
        return $vars;
    }

    /**
     * Get projects wp allocations to save
     *
     * @param   boolean     $currency_mode  The currency mode
     * @return  array
     */
    public function get_fee_area_allocation_vars_to_save($currency_mode)
    {
        $this->CI->load->library('Hoai_tools');
        $this->CI->load->model('Work_packages_model', 'work_packages', true);

        $this_request_vars = new stdClass();
        $this_request_vars->project = $this->get_project_id();
        $work_packages_list = $this->CI->work_packages->get_list($this_request_vars->project, Work_packages_model::WHICH_FEE_AREA_TREE);
        
        $data = array();
        foreach($this->fee_allocation_vars as $offer_id => $fee_allocation_vars) {
            if(empty($data[$offer_id])) {
                $data[$offer_id] = array();
            }
            
            foreach ($work_packages_list as $work_package_item) {
                $costs = null;
                if (array_key_exists('costs_' . $work_package_item->id, $fee_allocation_vars)) {
                    $costs = $fee_allocation_vars['costs_' . $work_package_item->id];
                } else {
                    continue;
                }
                
                $quantity = 1;
                if (isset($fee_allocation_vars['quantity_' . $work_package_item->id])) {
                    $quantity = $fee_allocation_vars['quantity_' . $work_package_item->id];
                }
                $unit = null;
                if (isset($fee_allocation_vars['unit_' . $work_package_item->id])) {
                    $unit = $fee_allocation_vars['unit_' . $work_package_item->id];
                }
                $price = 0;
                if (isset($fee_allocation_vars['price_' . $work_package_item->id])) {
                    $price = $fee_allocation_vars['price_' . $work_package_item->id];
                }
                $costs_view = 0;
                if (isset($fee_allocation_vars['costs_view_' . $work_package_item->id])) {
                    $costs_view = $fee_allocation_vars['costs_view_' . $work_package_item->id];
                }
                $supplement = 0;
                if (isset($fee_allocation_vars['supplement_' . $work_package_item->id])) {
                    $supplement = $fee_allocation_vars['supplement_' . $work_package_item->id];
                }
                $extras = 0;
                if (isset($fee_allocation_vars['extras_' . $work_package_item->id])) {
                    $extras = $fee_allocation_vars['extras_' . $work_package_item->id];
                }
                $rebate = 0;
                if (isset($fee_allocation_vars['rebate_' . $work_package_item->id])) {
                    $rebate = $fee_allocation_vars['rebate_' . $work_package_item->id];
                }

                if (empty($currency_mode)) {
                    $data[$offer_id][$work_package_item->id] = array(
                        'quantity'              => $quantity,
                        'quantity_id'           => $unit,
                        'price'                 => round($price, 2),
                        'costs'                 => round($costs, 2),
                        'supplement'            => round($supplement, 2),
                        'extras'                => round($extras, 2),
                        'rebate'                => round($rebate, 2),
                        'costs_view'            => round($costs_view, 2)
                    );
                } else {
                    $data[$offer_id][$work_package_item->id] = array(
                        'quantity'              => $quantity,
                        'quantity_id'           => $unit,
                        'price'                 => round($price, 2),
                        'costs'                 => round($costs*usnumber_to_float($this->exchange_rate), 2),
                        'costs_otcurr'          => round($costs, 2),
                        'supplement'            => round($supplement*usnumber_to_float($this->exchange_rate), 2),
                        'supplement_otcurr'     => round($supplement, 2),
                        'extras'                => round($extras*usnumber_to_float($this->exchange_rate), 2),
                        'extras_otcurr'         => round($extras, 2),
                        'rebate'                => round($rebate*usnumber_to_float($this->exchange_rate), 2),
                        'rebate_otcurr'         => round($rebate, 2),
                        'costs_view'            => round($costs_view*usnumber_to_float($this->exchange_rate), 2)
                    );
                }
            }
        }
        
        return $data;
    }
    
    /**
     * Get projects wp allocations to save
     *
     * @param   boolean     $currency_mode  The currency mode
     * @return  array
     */
    public function get_wp_allocation_vars_to_save($currency_mode)
    {
        $this->CI->load->model('Work_packages_model', 'work_packages', true);
        
        $this_request_vars = new stdClass();
        $this_request_vars->project = $this->get_project_id();
        $work_packages_list = $this->CI->work_packages->get_list($this_request_vars->project, Work_packages_model::WHICH_FEE_AREA_TREE, null, true); 
        
        $data = array();
        $turnover_rate = usnumber_to_float($this->turnover_rate);
        
        foreach ($work_packages_list as $work_package_item) {
            $data_item = array(
                'quantity'              => null,
                'quantity_id'           => null,
                'price'                 => null,
                'value'                 => null,
                'value_otcurr'          => null,
                'value_pre_tax'         => null,
                'value_pre_tax_otcurr'  => null,
                'project_id'            => $this_request_vars->project
            );  
            if (isset($this->wp_allocation_vars['fee_wp_'.$work_package_item->id.'_quantity'])) {
                $quantity = 0;
                $string_quantity = $this->wp_allocation_vars['fee_wp_'.$work_package_item->id.'_quantity'];
                $quantity = (is_float($string_quantity)) ? $string_quantity : usnumber_to_float($string_quantity);
                
                $data_item['quantity']              = $quantity;
            }
            if (isset($this->wp_allocation_vars['fee_wp_'.$work_package_item->id.'_quantity_id'])) {
                $quantity_id = 0;
                $string_quantity_id = $this->wp_allocation_vars['fee_wp_'.$work_package_item->id.'_quantity_id'];
                $quantity_id = (is_float($string_quantity_id)) ? $string_quantity_id : usnumber_to_float($string_quantity_id);
                
                $data_item['quantity_id']           = $quantity_id;
            }
            if (isset($this->wp_allocation_vars['fee_wp_'.$work_package_item->id.'_price'])) {
                $price = 0;
                $string_price = $this->wp_allocation_vars['fee_wp_'.$work_package_item->id.'_price'];
                $price = (is_float($string_price)) ? $string_price : usnumber_to_float($string_price);
                $price_otcurr = $price;
                
                if ($price!==null && $currency_mode) {
                    $exchange_rate = usnumber_to_float($this->exchange_rate);
                    $price = $price_otcurr*$exchange_rate;
                }
                
                $data_item['price']                 = $price_otcurr;
            }
            
            $costs = 0;
            if (isset($this->wp_allocation_vars['fee_wp_'.$work_package_item->id])) {
                $costs = 0;
                $string_costs = $this->wp_allocation_vars['fee_wp_'.$work_package_item->id];
                $costs = (is_float($string_costs)) ? $string_costs : usnumber_to_float($string_costs);
            }

            $costs_otcurr = 0;
            if (isset($this->wp_allocation_vars['fee_wp_'.$work_package_item->id.'_otcurr'])) {
                $string_costs_otcurr = $this->wp_allocation_vars['fee_wp_'.$work_package_item->id.'_otcurr'];
                $costs_otcurr = (is_float($string_costs_otcurr)) ? $string_costs_otcurr : usnumber_to_float($string_costs_otcurr);
            }
            
            if(empty($costs_otcurr) && !empty($costs) && $currency_mode) {
                $costs_otcurr = $costs;
                $exchange_rate = usnumber_to_float($this->exchange_rate);
                $costs = $costs_otcurr*$exchange_rate;
            }
            
            $data_item['value']                 = $costs;
            $data_item['value_otcurr']          = $costs_otcurr;
            $data_item['value_pre_tax']         = ($costs*$turnover_rate)+$costs;
            $data_item['value_pre_tax_otcurr']  = ($costs_otcurr*$turnover_rate)+$costs_otcurr;
            
            if ($this->is_done===false) {
                $data_item['done_pre_tax'] = 0;
                if ($currency_mode) {
                    $data_item['done_pre_tax_otcurr'] = 0;
                } else {
                    $data_item['done_pre_tax_otcurr'] = null;
                }
            }
            $data[$work_package_item->id] = $data_item;
        }
        
        return $data;
    }
    
     /**
     * Get projects wp allocations to save
     * 
     * @param   integer     $project_id     Project ID
     * @param   boolean     $currency_mode  The currency mode
     *
     * @return  array
     */
    public function get_wp_allocation_vars_to_savesdd($project_id, $currency_mode)
    {
        $this->CI->load->model('Work_packages_model', 'work_packages', true);
        
        $this_request_vars = new stdClass();
        $this_request_vars->project = $project_id;
        $work_packages_list = $this->CI->work_packages->get_list($this_request_vars->project, Work_packages_model::WHICH_FEE_AREA_TREE, null, true); 
        
        $data = array();
        foreach ($work_packages_list as $work_package_item) {
            $costs = 0;
            if (isset($this->wp_sddallocation_vars['fee_wp_sdd_'.$work_package_item->id])) {
                $costs = $this->wp_sddallocation_vars['fee_wp_sdd_'.$work_package_item->id];
                $costs_otcurr = $costs;
                
                if ($costs!==null && $currency_mode) {
                    $exchange_rate = usnumber_to_float($this->sdd_exchange_rate);
                    $costs = $costs_otcurr*$exchange_rate;
                }
                
                $data[$work_package_item->id] = array(
                    'value_pre_tax'         => $costs,
                    'value_pre_tax_otcurr'  => $costs_otcurr,
                    'project_id'            => $this_request_vars->project
                );  
            } else {
                $data[$work_package_item->id] = array(
                    'value_pre_tax'         => 0,
                    'value_pre_tax_otcurr'  => 0,
                    'project_id'            => $this_request_vars->project
                );  
            }
        }
        return $data;
    }

} // END class Fees_values
