<commit_before><?php

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of Tax
 *
 * @author eran
 */
abstract class Billrun_Calculator_Tax extends Billrun_Calculator {

	static protected $type = 'tax';
	
	protected $config = array();
	protected $nonTaxableTypes = array();

	public function __construct($options = array()) {
		parent::__construct($options);
		$this->config = Billrun_Factory::config()->getConfigValue('taxation',array());
		$this->nonTaxableTypes = Billrun_Factory::config('taxation.non_taxable_types', array());
	}

	public function updateRow($row) {
		Billrun_Factory::dispatcher()->trigger('beforeCalculatorUpdateRow', array(&$row, $this));
		$current = $row instanceof Mongodloid_Entity ? $row->getRawData() : $row;
		if (!$this->isLineTaxable($current)) {
			$newData = $current;
			$newData['final_charge'] = $newData['aprice'];
			if($this->isLinePreTaxed($current)) {
				$taxFactor = Billrun_Billrun::getVATByBillrunKey(Billrun_Billrun::getActiveBillrun());
				$newData['tax_data'] = [
									'total_amount'=> $this->getLinePriceToTax($current),
									'total_tax' => $taxFactor,
									'taxes' =>  [
												'tax'=> $taxFactor, 'amount' => $this->getLinePriceToTax($current) , 'description' => Billrun_Factory::config()->getConfigValue('taxation.vat_label', 'VAT') , 'pass_to_customer'=> 1
											]
									];
			} else {
				$newData['tax_data'] = [ 'total_amount' => 0, 'total_tax' => 0, 'taxes'=> []];
			}
		} else {
			if( $problemField = $this->isLineDataComplete($current) ) {
				Billrun_Factory::log("Line {$current['stamp']} is missing/has illigeal value in fields ".  implode(',', $problemField). ' For calcaulator '.$this->getType() );
				return FALSE;
			}
			$subscriber = new Billrun_Subscriber_Db();
			$subscriber->load(array('sid'=>$current['sid'],'time'=>date('Ymd H:i:sP',$current['urt']->sec)));
			$account = new Billrun_Account_Db();
			$account->load(array('aid'=>$current['aid'],'time'=>date('Ymd H:i:sP',$current['urt']->sec)));
			$newData = $this->updateRowTaxInforamtion($current, $subscriber->getSubscriberData(),$account->getCustomerData());
		
			//If we could not find the taxing information.
			if($newData == FALSE) {
				return FALSE;
			}
		}
		
		if($row instanceof Mongodloid_Entity ) {
			$row->setRawData($newData);
		} else {
			$row = $newData;
		}
		$row['final_charge']  = $row['tax_data']['total_amount'] + $row['aprice'];
		Billrun_Factory::dispatcher()->trigger('afterCalculatorUpdateRow', array(&$row, $this));
		return $row;
	}

	/**
	 * stab function The  will probably  be no need to prepare data for taxing
	 * @param type $lines
	 * @return nothing
	 */
	public function prepareData($lines) { }

	
	//================================= Static =================================
	/**
	 *  Get  the  total amount with taxes  for a given line
	 * @param type $taxedLine a line *after* taxation  was applied to it.
	 * @return float the  price of the line including taxes
	 *				 or the same value if the tax could not be calcualted without the taxedLine
	 */
	public static function addTax($untaxedPrice, $taxedLine = NULL) {
		return $untaxedPrice + Billrun_Util::getFieldVal($taxedLine['tax_data']['tax_amount'],0);
	}

	/**
	 *  Remove the taxes from the total amount with taxes for a given line
	 * @param type $taxedLine a line *after* taxation  was applied to it.
	 * @return float the price of the line including taxes \
	 *				 or the same value if the tax could not be calcualted without the taxedLine
	 */
	public static function removeTax($taxedPrice, $taxedLine = NULL) {
		return $taxedPrice - Billrun_Util::getFieldVal($taxedLine['tax_data']['tax_amount'],0);
	}

	/**
	 * Check if the  line is pre taxed
	 * @param $line  The Usage/Service/Plan CDR  to check for being  pretexed
	 * return TRUE if the line/CDR is pre taxed  FALSE otherwise
	 */
	 public static function isLinePreTaxed($line) {
		$userFields = $line['uf'];
		$usageType = $line['usaget'];
		$prepricedMapping = Billrun_Factory::config()->getFileTypeSettings($line['type'], true)['tax_included'];

		return !empty($prepricedMapping[$usageType]['aprice_field']);
	 }
	
	//================================ Protected ===============================	

	/**
	 * Get the price value to be used for taxation in the CDR
	 *
	 * @param  $line the  line to  retrive the  price  from.
	 * @return price The price that ins found in the line if not found then FALSE is returned.
	 */
	protected function getLinePriceToTax($line) {
		if($this->isLinePreTaxed($line)) {
			$userFields = $line['uf'];
			$usageType = $line['usaget'];
			$prepricedMapping = Billrun_Factory::config()->getFileTypeSettings($line['type'], true)['pricing'];
			$apriceField = isset($prepricedMapping[$usageType]['aprice_field']) ? $prepricedMapping[$usageType]['aprice_field'] : null;
			$aprice = Billrun_util::getIn($userFields, $apriceField);
			if (!is_null($aprice) && is_numeric($aprice)) {
				$apriceMult = isset($prepricedMapping[$usageType]['aprice_mult']) ? $prepricedMapping[$usageType]['aprice_mult'] : null;
				if (!is_null($apriceMult) && is_numeric($apriceMult)) {
					$aprice *= $apriceMult;
				}
				return $aprice;
			}
		}

		if(!isset($line['aprice'])) {
			Billrun_Factory::log("Line {$line['stamp']} has no pricing field legitimate for taxation", Zend_Log::ALERT);
		}
		return $line['aprice'] ?: FALSE;
	}

	/**
	 * Retrive all queued lines except from those that are configured not to be retrived.
	 * @return type
	 */
	protected function getLines() {
		return $this->getQueuedLines( array( 'type' => array( '$nin' => $this->nonTaxableTypes ) ) );
	}

	public function getCalculatorQueueType() {
		return 'tax';
	}

	public function isLineLegitimate($line) {
		return empty($line['skip_calc']) || !in_array(static::$type, $line['skip_calc']);
	}	
	
	protected function isLineTaxable($line) {
		$rate = $this->getRateForLine($line);

		return  (!empty($line[Billrun_Calculator_Rate::DEF_CALC_DB_FIELD]) && @$rate['vatable'] && !$this->isLinePreTaxed($line))
					|| 
				( $line['usaget'] == 'flat' && (!isset($rate['vatable']) || !empty($rate['vatable'])) );
	}
	
	protected function isLineDataComplete($line) {
		$missingFields = array_diff( array('aid'), array_keys($line) );
		return empty($missingFields) ? FALSE : $missingFields;
	}

	/**
	 * Update the line/row with it related taxing data.
	 * @param array $line The line to update it data.
	 * @param array $subscriber  the subscriber that is associated with the line
	 * @return array updated line/row with the tax data
	 */
	abstract protected function updateRowTaxInforamtion($line, $subscriber, $account);
	
	protected function getRateForLine($line) {
		$rate = FALSE;
		if(!empty($line['arate'])) {
			$rate = @Billrun_Rates_Util::getRateByRef($line['arate'])->getRawData();
		} else {
			$flatRate = $line['type'] == 'flat' ? 
				new Billrun_Plan(array('name'=> $line['name'], 'time'=> $line['urt']->sec)) : 
				new Billrun_Service(array('name'=> $line['name'], 'time'=> $line['urt']->sec));
			$rate = $flatRate->getData();
		}
		return $rate;			
	}
}
<commit_msg>BRCD_1695 : changed the  tax_included flag query to query the right field<commit_after><?php

/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of Tax
 *
 * @author eran
 */
abstract class Billrun_Calculator_Tax extends Billrun_Calculator {

	static protected $type = 'tax';
	
	protected $config = array();
	protected $nonTaxableTypes = array();

	public function __construct($options = array()) {
		parent::__construct($options);
		$this->config = Billrun_Factory::config()->getConfigValue('taxation',array());
		$this->nonTaxableTypes = Billrun_Factory::config('taxation.non_taxable_types', array());
	}

	public function updateRow($row) {
		Billrun_Factory::dispatcher()->trigger('beforeCalculatorUpdateRow', array(&$row, $this));
		$current = $row instanceof Mongodloid_Entity ? $row->getRawData() : $row;
		if (!$this->isLineTaxable($current)) {
			$newData = $current;
			$newData['final_charge'] = $newData['aprice'];
			if($this->isLinePreTaxed($current)) {
				$taxFactor = Billrun_Billrun::getVATByBillrunKey(Billrun_Billrun::getActiveBillrun());
				$newData['tax_data'] = [
									'total_amount'=> $this->getLinePriceToTax($current),
									'total_tax' => $taxFactor,
									'taxes' =>  [
												'tax'=> $taxFactor, 'amount' => $this->getLinePriceToTax($current) , 'description' => Billrun_Factory::config()->getConfigValue('taxation.vat_label', 'VAT') , 'pass_to_customer'=> 1
											]
									];
			} else {
				$newData['tax_data'] = [ 'total_amount' => 0, 'total_tax' => 0, 'taxes'=> []];
			}
		} else {
			if( $problemField = $this->isLineDataComplete($current) ) {
				Billrun_Factory::log("Line {$current['stamp']} is missing/has illigeal value in fields ".  implode(',', $problemField). ' For calcaulator '.$this->getType() );
				return FALSE;
			}
			$subscriber = new Billrun_Subscriber_Db();
			$subscriber->load(array('sid'=>$current['sid'],'time'=>date('Ymd H:i:sP',$current['urt']->sec)));
			$account = new Billrun_Account_Db();
			$account->load(array('aid'=>$current['aid'],'time'=>date('Ymd H:i:sP',$current['urt']->sec)));
			$newData = $this->updateRowTaxInforamtion($current, $subscriber->getSubscriberData(),$account->getCustomerData());
		
			//If we could not find the taxing information.
			if($newData == FALSE) {
				return FALSE;
			}
		}
		
		if($row instanceof Mongodloid_Entity ) {
			$row->setRawData($newData);
		} else {
			$row = $newData;
		}
		$row['final_charge']  = $row['tax_data']['total_amount'] + $row['aprice'];
		Billrun_Factory::dispatcher()->trigger('afterCalculatorUpdateRow', array(&$row, $this));
		return $row;
	}

	/**
	 * stab function The  will probably  be no need to prepare data for taxing
	 * @param type $lines
	 * @return nothing
	 */
	public function prepareData($lines) { }

	
	//================================= Static =================================
	/**
	 *  Get  the  total amount with taxes  for a given line
	 * @param type $taxedLine a line *after* taxation  was applied to it.
	 * @return float the  price of the line including taxes
	 *				 or the same value if the tax could not be calcualted without the taxedLine
	 */
	public static function addTax($untaxedPrice, $taxedLine = NULL) {
		return $untaxedPrice + Billrun_Util::getFieldVal($taxedLine['tax_data']['tax_amount'],0);
	}

	/**
	 *  Remove the taxes from the total amount with taxes for a given line
	 * @param type $taxedLine a line *after* taxation  was applied to it.
	 * @return float the price of the line including taxes \
	 *				 or the same value if the tax could not be calcualted without the taxedLine
	 */
	public static function removeTax($taxedPrice, $taxedLine = NULL) {
		return $taxedPrice - Billrun_Util::getFieldVal($taxedLine['tax_data']['tax_amount'],0);
	}

	/**
	 * Check if the  line is pre taxed
	 * @param $line  The Usage/Service/Plan CDR  to check for being  pretexed
	 * return TRUE if the line/CDR is pre taxed  FALSE otherwise
	 */
	 public static function isLinePreTaxed($line) {
		$userFields = $line['uf'];
		$usageType = $line['usaget'];
		$prepricedMapping = Billrun_Factory::config()->getFileTypeSettings($line['type'], true)['pricing'];

		return !empty($prepricedMapping[$usageType]['tax_included']);
	 }
	
	//================================ Protected ===============================	

	/**
	 * Get the price value to be used for taxation in the CDR
	 *
	 * @param  $line the  line to  retrive the  price  from.
	 * @return price The price that ins found in the line if not found then FALSE is returned.
	 */
	protected function getLinePriceToTax($line) {
		if($this->isLinePreTaxed($line)) {
			$userFields = $line['uf'];
			$usageType = $line['usaget'];
			$prepricedMapping = Billrun_Factory::config()->getFileTypeSettings($line['type'], true)['pricing'];
			$apriceField = isset($prepricedMapping[$usageType]['aprice_field']) ? $prepricedMapping[$usageType]['aprice_field'] : null;
			$aprice = Billrun_util::getIn($userFields, $apriceField);
			if (!is_null($aprice) && is_numeric($aprice)) {
				$apriceMult = isset($prepricedMapping[$usageType]['aprice_mult']) ? $prepricedMapping[$usageType]['aprice_mult'] : null;
				if (!is_null($apriceMult) && is_numeric($apriceMult)) {
					$aprice *= $apriceMult;
				}
				return $aprice;
			}
		}

		if(!isset($line['aprice'])) {
			Billrun_Factory::log("Line {$line['stamp']} has no pricing field legitimate for taxation", Zend_Log::ALERT);
		}
		return $line['aprice'] ?: FALSE;
	}

	/**
	 * Retrive all queued lines except from those that are configured not to be retrived.
	 * @return type
	 */
	protected function getLines() {
		return $this->getQueuedLines( array( 'type' => array( '$nin' => $this->nonTaxableTypes ) ) );
	}

	public function getCalculatorQueueType() {
		return 'tax';
	}

	public function isLineLegitimate($line) {
		return empty($line['skip_calc']) || !in_array(static::$type, $line['skip_calc']);
	}	
	
	protected function isLineTaxable($line) {
		$rate = $this->getRateForLine($line);

		return  (!empty($line[Billrun_Calculator_Rate::DEF_CALC_DB_FIELD]) && @$rate['vatable'] && !$this->isLinePreTaxed($line))
					|| 
				( $line['usaget'] == 'flat' && (!isset($rate['vatable']) || !empty($rate['vatable'])) );
	}
	
	protected function isLineDataComplete($line) {
		$missingFields = array_diff( array('aid'), array_keys($line) );
		return empty($missingFields) ? FALSE : $missingFields;
	}

	/**
	 * Update the line/row with it related taxing data.
	 * @param array $line The line to update it data.
	 * @param array $subscriber  the subscriber that is associated with the line
	 * @return array updated line/row with the tax data
	 */
	abstract protected function updateRowTaxInforamtion($line, $subscriber, $account);
	
	protected function getRateForLine($line) {
		$rate = FALSE;
		if(!empty($line['arate'])) {
			$rate = @Billrun_Rates_Util::getRateByRef($line['arate'])->getRawData();
		} else {
			$flatRate = $line['type'] == 'flat' ? 
				new Billrun_Plan(array('name'=> $line['name'], 'time'=> $line['urt']->sec)) : 
				new Billrun_Service(array('name'=> $line['name'], 'time'=> $line['urt']->sec));
			$rate = $flatRate->getData();
		}
		return $rate;			
	}
}

{'fraction_non_alphanumeric': 0.17752901586429504, 'fraction_numerical': 0.0009614724263443445, 'mean_word_length': 4.628913799768071, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 107, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1346101', 'n_tokens_mistral': 5148, 'n_tokens_neox': 4562, 'n_words': 1100}