<?php

  /**
   * InvoiceItem class
   * 
   * @package activeCollab.modules.invoicing
   * @subpackage models
   */
  class InvoiceItem extends BaseInvoiceItem {

    
    /**
     * Return tax value column text
     * 
     * @return string
     * 
     */
    function getTaxColumnValueText() {
      $invoice = Invoices::findById($this->getInvoiceId());
      
      if($this->getTax() == 0) {
        $column_text = '--';
      } else {
        if($invoice->commonTaxRate() instanceof TaxRate) {
          $column_text = $this->getTax();
        } else {
          AngieApplication::useHelper('money',GLOBALIZATION_FRAMEWORK,'modifier');
          
          $column_text = $this->getTaxRate()->getName() . " (" . $this->getTaxRate()->getVerbosePercentage() . ")" . " " . smarty_modifier_money($this->getTax());
        }//if
      }//if
      return $column_text;
    }//getTaxColumnValueText
    
    
    
    /**
     * Cached tax rate instance
     *
     * @var TaxRate
     */
    var $tax_rate = false;
    
    /**
     * Return related tax rate
     *
     * @return TaxRate
     */
    function getTaxRate() {
      if($this->tax_rate === false) {
        $this->tax_rate = TaxRates::findById($this->getTaxRateId());
      } // if
      return $this->tax_rate;
    } // getTaxRate
    
    /**
     * Return tax rate name string
     *
     * @return string
     */
    function getTaxRateName() {
      return $this->getTaxRate() instanceof TaxRate ? $this->getTaxRate()->getName() : '--';
    } // getTaxRateName
    
    /**
     * Return tax rate value string
     *
     * @return string
     */
    function getTaxRatePercentageVerbose() {
      return $this->getTaxRate() instanceof TaxRate ? '(' . $this->getTaxRate()->getVerbosePercentage() . ')' : '';
    } // getTaxRatePercentage
    
    /**
     * Return subtotal total cost of this item
     *
     * @return float
     */
    function getSubTotal() {
      return $this->getUnitCost() * $this->getQuantity();
    } // getSubTotal
    
    /**
     * Returns full price of the item
     * 
     * @return float
     */
    function getTotal() {
      return $this->getSubTotal() + $this->getTax();
    } // getTotal 
    
    /**
     * Return tax
     *
     * @return float
     */
    function getTax() {
      return $this->getTaxRate() instanceof TaxRate ? $this->getSubTotal() * $this->getTaxRate()->getPercentage() / 100 : 0;
    } // getTax
    
    /**
     * Set ID-s of related time records
     *
     * @param array $ids
     * @return boolean
     */
    function setTimeRecordIds($ids) {
      DB::beginWork();
      
      $execute = DB::execute('DELETE FROM ' . TABLE_PREFIX . 'invoice_related_records WHERE invoice_id = ? && item_id = ? && parent_type=?', $this->getInvoiceId(), $this->getId(), 'TimeRecord');
      if($execute && !is_error($execute)) {
        if(is_foreachable($ids)) {
          $to_insert = array();
          $invoice_id = $this->getInvoiceId();
          $item_id = $this->getId();
          
          foreach($ids as $id) {
            $id = (integer) $id;
            if($id && !isset($to_insert[$id])) {
              $to_insert[$id] = "($invoice_id, $item_id, $id, 'TimeRecord')";
            } // if
          } // foreach
          
          if(is_foreachable($to_insert)) {
            $execute = DB::execute('INSERT INTO ' . TABLE_PREFIX . 'invoice_related_records (invoice_id, item_id, parent_id, parent_type) VALUES ' . implode(', ', $to_insert));
            if(!$execute || is_error($execute)) {
              DB::rollback();
              return $execute;
            } // if
          } // if
        } // if
        
        DB::commit();
        return true;
      } else {
        DB::rollback();
        return $execute;
      } // if
    } // setTimeRecordIds
    
    /**
     * Retrieve TimeRecordIds
     * 
     * @return array
     */
    function getTimeRecordIds() {
      $execute = DB::execute('SELECT `parent_id` FROM ' . TABLE_PREFIX . 'invoice_related_records WHERE invoice_id = ? && item_id = ? && parent_type=?', $this->getInvoiceId(), $this->getId(), 'TimeRecord');
      if ($execute && !is_error($execute)) {
        if (is_foreachable($execute)) {
          $time_record_ids = array();
          foreach ($execute as $time_record) {
          	$time_record_ids[] = $time_record['parent_id'];
          } // foreach
          return $time_record_ids;
        } // if
        return null;
      } else {
        return $execute;
      } // if
    } // getTimeRecordIds
    
    
    /**
     * Set ID-s of related expenses
     *
     * @param array $ids
     * @return boolean
     */
    function setExpensesIds($ids) {
      DB::beginWork();
      
      $execute = DB::execute('DELETE FROM ' . TABLE_PREFIX . 'invoice_related_records WHERE invoice_id = ? && item_id = ? && parent_type = ?', $this->getInvoiceId(), $this->getId(),'Expense');
      if($execute && !is_error($execute)) {
        if(is_foreachable($ids)) {
          $to_insert = array();
          $invoice_id = $this->getInvoiceId();
          $item_id = $this->getId();
          
          foreach($ids as $id) {
            $id = (integer) $id;
            if($id && !isset($to_insert[$id])) {
              $to_insert[$id] = "($invoice_id, $item_id, $id, 'Expense')";
            } // if
          } // foreach
          
          if(is_foreachable($to_insert)) {
            $execute = DB::execute('INSERT INTO ' . TABLE_PREFIX . 'invoice_related_records (invoice_id, item_id, parent_id, parent_type) VALUES ' . implode(', ', $to_insert));
            if(!$execute || is_error($execute)) {
              DB::rollback();
              return $execute;
            } // if
          } // if
        } // if
        
        DB::commit();
        return true;
      } else {
        DB::rollback();
        return $execute;
      } // if
    } // setExpensesIds
    
    /**
     * Retrieve ExpensesIds
     * 
     * @return array
     */
    function getExpensesIds() {
      $execute = DB::execute('SELECT `parent_id` FROM ' . TABLE_PREFIX . 'invoice_related_records WHERE invoice_id = ? && item_id = ? && parent_type = ?', $this->getInvoiceId(), $this->getId(), 'Expense');
      if ($execute && !is_error($execute)) {
        if (is_foreachable($execute)) {
          $expenses_ids = array();
          foreach ($execute as $expense) {
          	$expenses_ids[] = $expense['parent_id'];
          } // foreach
          return $expenses_ids;
        } // if
        return null;
      } else {
        return $execute;
      } // if
    } // if
  
    // ---------------------------------------------------
    //  System
    // ---------------------------------------------------
    
    /**
     * Return array or property => value pairs that describes this object
     *
     * $user is an instance of user who requested description - it's used to get
     * only the data this user can see
     *
     * @param IUser $user
     * @param boolean $detailed
     * @param boolean $for_interface
     * @return array
     */
    function describe(IUser $user, $detailed = false, $for_interface = false) {
    	$result = parent::describe($user, $detailed, $for_interface);
    	
    	unset($result['name']);
    	
    	$result['description'] = $this->getDescription();
    	
    	$result['unit_cost'] = $this->getUnitCost();
    	$result['quantity'] = $this->getQuantity();
    	
      $result['subtotal'] = $this->getSubTotal();
      $result['tax'] = array(
        'id'	=> $this->getTaxRateId(),
        'name' => $this->getTaxRateName(),
        'value' => $this->getTax(),
        'verbose_percentage' => $this->getTaxRatePercentageVerbose()
      );

      $result['total'] = $this->getTotal();
      $result['position'] = $this->getPosition();

      return $result;
    } // describe

    /**
     * Return array or property => value pairs that describes this object
     *
     * @param IUser $user
     * @param boolean $detailed
     * @return array
     */
    function describeForApi(IUser $user, $detailed = false) {
      $result = parent::describe($user, $detailed);

      unset($result['name']);

      $result['description'] = $this->getDescription();

      $result['unit_cost'] = $this->getUnitCost();
      $result['quantity'] = $this->getQuantity();

      $result['subtotal'] = $this->getSubTotal();
      $result['tax'] = array(
        'id'	=> $this->getTaxRateId(),
        'name' => $this->getTaxRateName(),
        'value' => $this->getTax(),
        'verbose_percentage' => $this->getTaxRatePercentageVerbose()
      );

      $result['total'] = $this->getTotal();
      $result['position'] = $this->getPosition();

      return $result;
    } // describeForApi

    /**
     * Validate before save
     *
     * @param ValidationErrors $errors
     */
    function validate(ValidationErrors &$errors) {
      if(!$this->validatePresenceOf('description')) {
        $errors->addError(lang('Item description is required'), 'name');
      } // if
      
      if(!$this->validatePresenceOf('quantity')) {
        $errors->addError(lang('Quantity is required'), 'quantity');
      } // if
      
      if (!$this->getUnitCost()) {
        $this->setUnitCost(0);
      } // if
      
      return parent::validate($errors);
    } // validate
  
  }