<commit_before><?php

/**
 * @package         Billing
 * @copyright       Copyright (C) 2012-2016 BillRun Technologies Ltd. All rights reserved.
 * @license         GNU Affero General Public License Version 3; see LICENSE.txt
 */
/*
 * 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.
 */

/**
 * This class is to hold the logic for the Cards module.
 *
 * @package  Models
 * @subpackage Table
 * @since    4.0
 */
class ReportModel {
	
	protected $config = null;
	protected $report = null;
	protected $cacheFormatStyle = [];
	
	/**
	 *  Array of entity join map keys
	 */
	protected $mapJoin = array(
		'usage' => array(
			'subscription' => array(
				'source_field' => 'sid',
				'target_field' => 'sid',
			),
			'customer' => array(
				'source_field' => 'aid',
				'target_field' => 'aid',
			),
		),
		'subscription' => array(
			'usage' => array(
				'source_field' => 'sid',
				'target_field' => 'sid',
			),
			'customer' => array(
				'source_field' => 'aid',
				'target_field' => 'aid',
			),
		)
	);
	
	/**
	 * Array of entities with revision
	 */
	protected $entityWithRevisions = array('subscription', 'customer');
	
	/**
	 * Fields that are complex object
	 */
	protected $pluckFields = array(
		array(
			'key' => 'name',
			'fields' => array('$subscription.services', 'services'),
		),
	);

	/**
	 * constructor
	 * 
	 * @param array $params of parameters to preset the object
	 */
	public function __construct($report = null) { 
		$this->config = Billrun_Factory::config()->getConfigValue('api.config.aggregate');
		$this->setReport($report);
	}
	
	public function setReport($report = null) { 
		$this->report = $report;
	}
	
	/**
	 * getReportByKey
	 * 
	 * @param type $key
	 * @return type report
	 */
	public static function getReportByKey($key) {
		return Billrun_Factory::db()->reportsCollection()->query(array('key' => $key))->cursor()->current()->getRawData();
	}
	
	/**
	 * applyFilter
	 * 
	 * @param type $query
	 * @param type $page
	 * @param type $size
	 * @return type
	 */
	public function applyFilter($page, $size) {
		$collection = Billrun_Factory::db()->{$this->getCollection() . "Collection"}();
		$report_entity = $this->getReportEntity();
		
		$aggregate = array();
		
		$match = $this->getMatch($report_entity);
		if(!empty($match)) {
			$aggregate[] = array('$match' => $match);
		}
		
		$join_entities = $this->getReportJoinEntities();
		if(!empty($join_entities)) {
			if(!$this->isValidJoin($report_entity, $join_entities)) {
				$report_entities = implode(", ", $join_entities);
				throw new Exception("No support to join {$report_entity} with those entities: {$report_entities}");
			}
			foreach ($join_entities as $join_entity) {
				$lookup = $this->getLookup($join_entity);
				if(!empty($lookup)) {
					$aggregate[] = array('$lookup' => $lookup);
				}
				// filter by account type beacuse subscribers have AID field too 
				if($join_entity === 'customer' ) {
					$filterByType = $this->getFilterByType($join_entity, 'type', 'account');
					if(!empty($filterByType)) {
						$aggregate[] = array('$addFields' => $filterByType);
					}
				}
				if(in_array($join_entity, $this->entityWithRevisions)) {
					$filterByRevision = $this->getFilterByRevision($join_entity);
					if(!empty($filterByRevision)) {
						$aggregate[] = array('$addFields' => $filterByRevision);
					}
				}
				$unwind = $this->getUnwind($join_entity);
				if(!empty($unwind)) {
					$aggregate[] = array('$unwind' => $unwind);
				}

				$match = $this->getMatch($join_entity);
				if(!empty($match)) {
					$aggregate[] = array('$match' => $match);
				}
			}
		}


		$group = $this->getGroup();
		if(!empty($group)) {
			$aggregate[] = array('$group' => $group);
		}
		
		$project = $this->getProject();
		if(!empty($project)) {
			$aggregate[] = array('$project' => $project);
		}
		
		$sort = $this->getSort();
		if(!empty($sort)) {
			$aggregate[] = array('$sort' => $sort);
		}
		
		$skip = $this->getSkip($size, $page);
		if($skip !== -1) {
			$aggregate[] = array('$skip' => $skip);
		}
		
		$limit = $this->getLimit($size);
		if($limit !== -1) {
			$aggregate[] = array('$limit' => $limit);
		}
		
		$results = $collection->aggregate($aggregate);
		$rows = [];
		$formatters = $this->getFieldFormatters();
		foreach ($results as $result) {
			$row = $result->getRawData();
			$rows[] = $this->formatOutputRow($row, $formatters);
		}
		return $rows;
	}
	
	protected function isValidJoin($report_entity, $join_entities) {
		if (empty($this->mapJoin[$report_entity])) {
			return false;
		}
		$allowd_join_entities = array_keys($this->mapJoin[$report_entity]);
		return count(array_intersect($join_entities, $allowd_join_entities)) == count($join_entities);
	}
	
	protected function getRowsFormattersByKey($key, $formatters) {
		$formats = array();
		foreach ($formatters as $formatter) {
			if ($formatter['field'] === $key) {
				$formats[] = $formatter;<commit_msg>BRCD-1249: fix(Reports) - add filter by 'type'='subscriber' to join with subscription<commit_after><?php

/**
 * @package         Billing
 * @copyright       Copyright (C) 2012-2016 BillRun Technologies Ltd. All rights reserved.
 * @license         GNU Affero General Public License Version 3; see LICENSE.txt
 */
/*
 * 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.
 */

/**
 * This class is to hold the logic for the Cards module.
 *
 * @package  Models
 * @subpackage Table
 * @since    4.0
 */
class ReportModel {
	
	protected $config = null;
	protected $report = null;
	protected $cacheFormatStyle = [];
	
	/**
	 *  Array of entity join map keys
	 */
	protected $mapJoin = array(
		'usage' => array(
			'subscription' => array(
				'source_field' => 'sid',
				'target_field' => 'sid',
			),
			'customer' => array(
				'source_field' => 'aid',
				'target_field' => 'aid',
			),
		),
		'subscription' => array(
			'usage' => array(
				'source_field' => 'sid',
				'target_field' => 'sid',
			),
			'customer' => array(
				'source_field' => 'aid',
				'target_field' => 'aid',
			),
		)
	);
	
	/**
	 * Array of entities with revision
	 */
	protected $entityWithRevisions = array('subscription', 'customer');
	
	/**
	 * Fields that are complex object
	 */
	protected $pluckFields = array(
		array(
			'key' => 'name',
			'fields' => array('$subscription.services', 'services'),
		),
	);

	/**
	 * constructor
	 * 
	 * @param array $params of parameters to preset the object
	 */
	public function __construct($report = null) { 
		$this->config = Billrun_Factory::config()->getConfigValue('api.config.aggregate');
		$this->setReport($report);
	}
	
	public function setReport($report = null) { 
		$this->report = $report;
	}
	
	/**
	 * getReportByKey
	 * 
	 * @param type $key
	 * @return type report
	 */
	public static function getReportByKey($key) {
		return Billrun_Factory::db()->reportsCollection()->query(array('key' => $key))->cursor()->current()->getRawData();
	}
	
	/**
	 * applyFilter
	 * 
	 * @param type $query
	 * @param type $page
	 * @param type $size
	 * @return type
	 */
	public function applyFilter($page, $size) {
		$collection = Billrun_Factory::db()->{$this->getCollection() . "Collection"}();
		$report_entity = $this->getReportEntity();
		
		$aggregate = array();
		
		$match = $this->getMatch($report_entity);
		if(!empty($match)) {
			$aggregate[] = array('$match' => $match);
		}
		
		$join_entities = $this->getReportJoinEntities();
		if(!empty($join_entities)) {
			if(!$this->isValidJoin($report_entity, $join_entities)) {
				$report_entities = implode(", ", $join_entities);
				throw new Exception("No support to join {$report_entity} with those entities: {$report_entities}");
			}
			foreach ($join_entities as $join_entity) {
				$lookup = $this->getLookup($join_entity);
				if(!empty($lookup)) {
					$aggregate[] = array('$lookup' => $lookup);
				}
				// filter by account type beacuse subscribers collection is mixed 
				if($join_entity === 'customer' ) {
					$filterByType = $this->getFilterByType($join_entity, 'type', 'account');
					if(!empty($filterByType)) {
						$aggregate[] = array('$addFields' => $filterByType);
					}
				}
				// filter by subscriber type beacuse subscribers collection is mixed 
				if($join_entity === 'subscription' ) {
					$filterByType = $this->getFilterByType($join_entity, 'type', 'subscriber');
					if(!empty($filterByType)) {
						$aggregate[] = array('$addFields' => $filterByType);
					}
				}
				if(in_array($join_entity, $this->entityWithRevisions)) {
					$filterByRevision = $this->getFilterByRevision($join_entity);
					if(!empty($filterByRevision)) {
						$aggregate[] = array('$addFields' => $filterByRevision);
					}
				}
				$unwind = $this->getUnwind($join_entity);
				if(!empty($unwind)) {
					$aggregate[] = array('$unwind' => $unwind);
				}

				$match = $this->getMatch($join_entity);
				if(!empty($match)) {
					$aggregate[] = array('$match' => $match);
				}
			}
		}


		$group = $this->getGroup();
		if(!empty($group)) {
			$aggregate[] = array('$group' => $group);
		}
		
		$project = $this->getProject();
		if(!empty($project)) {
			$aggregate[] = array('$project' => $project);
		}
		
		$sort = $this->getSort();
		if(!empty($sort)) {
			$aggregate[] = array('$sort' => $sort);
		}
		
		$skip = $this->getSkip($size, $page);
		if($skip !== -1) {
			$aggregate[] = array('$skip' => $skip);
		}
		
		$limit = $this->getLimit($size);
		if($limit !== -1) {
			$aggregate[] = array('$limit' => $limit);
		}
		error_log(__FILE__ . '(' . __FUNCTION__ . ":" . __LINE__ . ") " . "\n" . "Data" . " :\n" . print_r(json_encode($aggregate), 1) . "\n");
		$results = $collection->aggregate($aggregate);
		$rows = [];
		$formatters = $this->getFieldFormatters();
		foreach ($results as $result) {
			$row = $result->getRawData();
			$rows[] = $this->formatOutputRow($row, $formatters);
		}
		return $rows;
	}
	
	protected function isValidJoin($report_entity, $join_entities) {
		if (empty($this->mapJoin[$report_entity])) {
			return false;
		}
		$allowd_join_entities = array_keys($this->mapJoin[$report_entity]);
		return count(array_intersect($join_entities, $allowd_join_entities)) == count($join_entities);
	}
	
	protected function getRowsFormattersByKey($key, $formatters) {
		$formats = array();
		foreach ($formatters as $formatter) {
			if ($formatter['field'] === $key) {
				$formats[] = $formatter;
{'fraction_non_alphanumeric': 0.18437706621328043, 'fraction_numerical': 0.00292811939170681, 'mean_word_length': 3.623580786026201, 'pattern_counts': {'":': 1, '<': 5, '<?xml version=': 0, '>': 125, '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': '790255', 'n_tokens_mistral': 4071, 'n_tokens_neox': 3430, 'n_words': 733}