/** * method that outputs account, subscribers and usage of requested accounts and requested date usage * it's called automatically by the api main controller */ public function execute() { Billrun_Factory::log()->log("Execute data triggers", Zend_Log::INFO); $request = $this->getRequest()->getRequest(); // supports GET / POST requests $params = array('plan', 'data_usage', 'from_account_id', 'to_account_id', 'billrun'); foreach ($params as $param) { if (!isset($request[$param])) { $msg = 'Missing required parameter: ' . $param; Billrun_Factory::log()->log($msg, Zend_Log::ERR); $this->getController()->setOutput(array(array('status' => 0, 'desc' => 'failed', 'output' => $msg))); return; } } Billrun_Factory::log()->log("Request params Received: plan-" . $request['plan'] . ", data_usage-" . $request['data_usage'] . ", from_account_id-" . $request['from_account_id'] . ", to_account_id-" . $request['to_account_id'] . ", billrun-" . $request['billrun'], Zend_Log::INFO); $balances = new BalancesModel(array('size' => Billrun_Factory::config()->getConfigValue('balances.accounts.limit', 50000))); $results = $balances->getBalancesVolume($request['plan'], $request['data_usage'], $request['from_account_id'], $request['to_account_id'], $request['billrun']); if (empty($results)) { Billrun_Factory::log()->log('Some error happen, no result, received parameters: ' . print_r($request, true), Zend_Log::ERR); return; } $counter = 0; $accounts = array(); foreach ($results as $result) { $accounts['aid'][$result['aid']]['subs'][$result['sid']] = Billrun_Util::byteFormat($result['balance']['totals']['data']['usagev'], 'MB', 2, false, '.', ''); $counter++; } $this->getController()->setOutput(array(array('status' => 1, 'desc' => 'success', 'subscribers_count' => $counter, 'output' => $accounts))); return true; }
public function processData() { foreach ($this->data['data'] as &$row) { $row['process_time'] = Billrun_Util::generateCurrentTime(); } return true; }
public function load($subscriberId, $billrunKey = NULL) { Billrun_Factory::log()->log("Trying to load balance " . $billrunKey . " for subscriber " . $subscriberId, Zend_Log::DEBUG); $billrunKey = !$billrunKey ? Billrun_Util::getBillrunKey(time()) : $billrunKey; $this->data = Billrun_Factory::db(array('name' => 'balances'))->balancesCollection()->query(array('sid' => $subscriberId, 'billrun_month' => $billrunKey))->cursor()->hint(array('sid' => 1, 'billrun_month' => 1))->limit(1)->current(); $this->data->collection(Billrun_Factory::db(array('name' => 'balances'))->balancesCollection()); }
public function getFilterFields() { $months = 6; $billruns = array(); $timestamp = time(); for ($i = 0; $i < $months; $i++) { $billrun_key = Billrun_Util::getBillrunKey($timestamp); if ($billrun_key >= '201401') { $billruns[$billrun_key] = $billrun_key; } else { break; } $timestamp = strtotime("1 month ago", $timestamp); } arsort($billruns); // $plansModel = new PlansModel(); // $plansCursor = $plansModel->getData(); // $plans = array(); // foreach ($plansCursor as $p) { // $plans[(string) $p->getId()->getMongoID()] = $p["name"]; // } $usage_filter_values = $this->getBalancesFields(); unset($usage_filter_values['aid'], $usage_filter_values['sid'], $usage_filter_values['billrun_month'], $usage_filter_values['current_plan']); // $usage_filter_values = array_merge($basic_columns, $extra_columns); $planNames = array_unique(array_keys(Billrun_Plan::getPlans()['by_name'])); $planNames = array_combine($planNames, $planNames); $operators = array('equals' => '=', 'lt' => '<', 'lte' => '<=', 'gt' => '>', 'gte' => '>='); $filter_fields = array('aid' => array('key' => 'aid', 'db_key' => 'aid', 'input_type' => 'number', 'comparison' => 'equals', 'display' => 'Account id', 'default' => ''), 'sid' => array('key' => 'sid', 'db_key' => 'sid', 'input_type' => 'number', 'comparison' => 'equals', 'display' => 'Subscriber id', 'default' => ''), 'usage_type' => array('key' => 'manual_key', 'db_key' => 'nofilter', 'input_type' => 'multiselect', 'display' => 'Usage', 'values' => $usage_filter_values, 'singleselect' => 1, 'default' => array()), 'usage_filter' => array('key' => 'manual_operator', 'db_key' => 'nofilter', 'input_type' => 'multiselect', 'display' => '', 'values' => $operators, 'singleselect' => 1, 'default' => array()), 'usage_value' => array('key' => 'manual_value', 'db_key' => 'nofilter', 'input_type' => 'number', 'display' => '', 'default' => ''), 'plan' => array('key' => 'plan', 'db_key' => 'current_plan', 'input_type' => 'multiselect', 'comparison' => '$in', 'ref_coll' => 'plans', 'ref_key' => 'name', 'display' => 'Plan', 'values' => $planNames, 'default' => array()), 'billrun' => array('key' => 'billrun', 'db_key' => 'billrun_month', 'input_type' => 'multiselect', 'comparison' => '$in', 'display' => 'Billrun', 'values' => $billruns, 'default' => array())); return array_merge($filter_fields, parent::getFilterFields()); }
/** * method to execute remove of billing lines (only credit and active) * it's called automatically by the api main controller */ public function execute() { Billrun_Factory::log()->log("Execute api remove", Zend_Log::INFO); $request = $this->getRequest()->getRequest(); // supports GET / POST requests Billrun_Factory::log()->log("Input: " . print_R($request, 1), Zend_Log::INFO); $stamps = array(); foreach ($request['stamps'] as $line_stamp) { $clear_stamp = Billrun_Util::filter_var($line_stamp, FILTER_SANITIZE_STRING, FILTER_FLAG_ALLOW_HEX); if (!empty($clear_stamp)) { $stamps[] = $clear_stamp; } } if (empty($stamps)) { Billrun_Factory::log()->log("remove action failed; no correct stamps", Zend_Log::INFO); $this->getController()->setOutput(array(array('status' => false, 'desc' => 'failed - invalid stamps input', 'input' => $request))); return true; } $model = new LinesModel(); $query = array('source' => 'api', 'stamp' => array('$in' => $stamps), '$or' => array(array('billrun' => array('$gte' => Billrun_Billrun::getActiveBillrun())), array('billrun' => array('$exists' => false)))); $ret = $model->remove($query); if (!isset($ret['ok']) || !$ret['ok'] || !isset($ret['n'])) { Billrun_Factory::log()->log("remove action failed pr miscomplete", Zend_Log::INFO); $this->getController()->setOutput(array(array('status' => false, 'desc' => 'remove failed', 'input' => $request))); return true; } Billrun_Factory::log()->log("remove success", Zend_Log::INFO); $this->getController()->setOutput(array(array('status' => $ret['n'], 'desc' => 'success', 'input' => $request))); }
/** * method to send * * @param type $message * @param type $recipients * @return \Billrun_Sms|boolean */ public function send($message, $recipients) { if (empty($message) || empty($recipients)) { Billrun_Factory::log()->log("can not send the sms, there are missing params - txt: " . $this->data['message'] . " recipients: " . print_r($this->data['recipients'], TRUE) . " from: " . $this->data['from'], Zend_Log::WARN); return false; } $unicode_text = $this->sms_unicode($message); if (!empty($message) && empty($unicode_text)) { $language = '1'; } else { $language = '2'; } // Temporary - make sure is not 23 chars long $text = str_pad($message, 24, '+'); $period = 120; foreach ($recipients as $recipient) { $send_params = array('message' => $text, 'to' => $recipient, 'from' => $this->data['from'], 'language' => $language, 'username' => $this->data['user'], 'password' => $this->data['pwd'], 'acknowledge' => "false", 'period' => $period, 'channel' => "SRV"); $url = $this->data['provisioning'] . "?" . http_build_query($send_params); $sms_result = Billrun_Util::sendRequest($url); $exploded = explode(',', $sms_result); $response = array('error-code' => empty($exploded[0]) ? 'error' : 'success', 'cause-code' => $exploded[1], 'error-description' => $exploded[2], 'tid' => $exploded[3]); Billrun_Factory::log()->log("phone: " . $recipient . " encoded_text: " . $message . " url: " . $url . " result" . print_R($response, 1), Zend_Log::INFO); } return $response['error-code'] == 'success' ? true : false; }
public function execute() { $request = $this->getRequest(); $aid = $request->get("aid"); $stamp = Billrun_Util::getBillrunKey(time()); $subscribers = $request->get("subscribers"); if (!is_numeric($aid)) { die; } if (is_string($subscribers)) { $subscribers = explode(",", $subscribers); } else { $subscribers = array(); } $options = array('type' => 'balance', 'aid' => $aid, 'subscribers' => $subscribers, 'stamp' => $stamp); $generator = Billrun_Generator::getInstance($options); if ($generator) { $generator->load(); header('Content-type: text/xml'); $generator->generate(); $this->getController()->setOutput(array(false, true)); // hack } else { $this->_controller->addOutput("Generator cannot be loaded"); } }
/** * method to execute the query * it's called automatically by the api main controller */ public function execute() { Billrun_Factory::log()->log("Execute api query billrun", Zend_Log::INFO); $request = $this->getRequest()->getRequest(); // supports GET / POST requests Billrun_Factory::log()->log("Input: " . print_R($request, 1), Zend_Log::INFO); if (!isset($request['aid'])) { $this->setError('Require to supply aid or sid', $request); return true; } $find = array(); $max_list = 1000; if (isset($request['aid'])) { $aids = Billrun_Util::verify_array($request['aid'], 'int'); if (count($aids) > $max_list) { $this->setError('Maximum of aid is ' . $max_list, $request); return true; } $find['aid'] = array('$in' => $aids); } if (isset($request['billrun'])) { $find['billrun_key'] = $this->getBillrunQuery($request['billrun']); } $options = array('sort' => array('aid', 'billrun_key')); $cacheParams = array('fetchParams' => array('options' => $options, 'find' => $find)); $this->setCacheLifeTime(604800); // 1 week $results = $this->cache($cacheParams); Billrun_Factory::log()->log("query success", Zend_Log::INFO); $ret = array(array('status' => 1, 'desc' => 'success', 'input' => $request, 'details' => $results)); $this->getController()->setOutput($ret); }
public function load($subscriberId, $billrunKey = NULL) { Billrun_Factory::log()->log("Trying to load balance " . $billrunKey . " for subscriber " . $subscriberId, Zend_Log::DEBUG); $billrunKey = !$billrunKey ? Billrun_Util::getBillrunKey(time()) : $billrunKey; $this->data = $this->collection->query(array('sid' => $subscriberId, 'billrun_month' => $billrunKey))->cursor()->setReadPreference('RP_PRIMARY')->hint(array('sid' => 1, 'billrun_month' => 1))->limit(1)->current(); // set the data collection to enable clear save $this->data->collection($this->collection); }
protected function parseRow($credit_row) { $ret = Billrun_Util::parseCreditRow($credit_row); if (isset($ret['status']) && $ret['status'] == 0) { $error_message = isset($ret['desc']) ? $ret['desc'] : 'Error with credit row'; return $this->setError($error_message, $credit_row); } return $ret; }
public function __construct($options) { parent::__construct($options); $this->reportType = isset($options['report_type']) ? $options['report_type'] : $this->reportType; $this->reportBasePath = Billrun_Factory::config()->getConfigValue($this->reportType . '.reports.path', './'); $this->types = Billrun_Factory::config()->getConfigValue($this->reportType . '.reports.types', array('I' => 'International', 'M' => 'Mobile', 'N' => 'National', '4' => 'National', 'P' => 'National', 'Un' => 'Other')); $this->startDate = isset($options['start_date']) ? strtotime($options['start_date']) : (strlen($this->stamp) > 8 ? strtotime($this->stamp) : Billrun_Util::getLastChargeTime(true)); $this->endDate = isset($options['end_date']) ? strtotime($options['end_date']) : strtotime(date('Ymt', $this->startDate)); }
/** * method to receive the balances lines that over requested date usage * * @return Mongodloid_Cursor Mongo cursor for iteration */ public function getBalancesVolume($plan, $data_usage, $from_account_id, $to_account_id, $billrun) { $params = array('name' => $plan, 'time' => Billrun_Util::getStartTime($billrun)); $plan_id = Billrun_Factory::plan($params); $id = $plan_id->get('_id')->getMongoID(); $data_usage_bytes = Billrun_Util::megabytesToBytesFormat((int) $data_usage); $query = array('aid' => array('$gte' => (int) $from_account_id, '$lte' => (int) $to_account_id), 'billrun_month' => $billrun, 'balance.totals.data.usagev' => array('$gt' => (double) $data_usage_bytes), 'current_plan' => Billrun_Factory::db()->plansCollection()->createRef($id)); // print_R($query);die; return $this->collection->query($query)->cursor()->setReadPreference(Billrun_Factory::config()->getConfigValue('read_only_db_pref'))->hint(array('aid' => 1, 'billrun_month' => 1))->limit($this->size); }
/** * method to execute the query * it's called automatically by the api main controller */ public function execute() { Billrun_Factory::log()->log("Execute api query aggregate", Zend_Log::INFO); $request = $this->getRequest()->getRequest(); // supports GET / POST requests Billrun_Factory::log()->log("Input: " . print_R($request, 1), Zend_Log::DEBUG); if (!isset($request['aid']) && !isset($request['sid'])) { $this->setError('Require to supply aid or sid', $request); return true; } $find = array(); $max_list = 1000; if (isset($request['aid'])) { $aids = Billrun_Util::verify_array($request['aid'], 'int'); if (count($aids) > $max_list) { $this->setError('Maximum of aid is ' . $max_list, $request); return true; } $find['aid'] = array('$in' => $aids); } if (isset($request['sid'])) { $sids = Billrun_Util::verify_array($request['sid'], 'int'); if (count($sids) > $max_list) { $this->setError('Maximum of sid is ' . $max_list, $request); return true; } $find['sid'] = array('$in' => $sids); } if (isset($request['billrun'])) { $find['billrun'] = $this->getBillrunQuery($request['billrun']); } if (isset($request['query'])) { $query = $this->getArrayParam($request['query']); $find = array_merge($find, (array) $query); } if (isset($request['groupby'])) { $groupby = array('_id' => $this->getArrayParam($request['groupby'])); } else { $groupby = array('_id' => null); } if (isset($request['aggregate'])) { $aggregate = $this->getArrayParam($request['aggregate']); } else { $aggregate = array('count' => array('$sum' => 1)); } $group = array_merge($groupby, $aggregate); $options = array('sort' => array('urt'), 'page' => isset($request['page']) && $request['page'] > 0 ? (int) $request['page'] : 0, 'size' => isset($request['size']) && $request['size'] > 0 ? (int) $request['size'] : 1000); $cacheParams = array('fetchParams' => array('options' => $options, 'find' => $find, 'group' => $group, 'groupby' => $groupby)); $this->setCacheLifeTime(604800); // 1 week $results = $this->cache($cacheParams); Billrun_Factory::log()->log("Aggregate query success", Zend_Log::INFO); $ret = array(array('status' => 1, 'desc' => 'success', 'input' => $request, 'details' => $results)); $this->getController()->setOutput($ret); }
/** * load the data to aggregate */ public function load() { $billrun_key = $this->getStamp(); $subscriber = Billrun_Factory::subscriber(); $filename = $billrun_key . '_leftover_aggregator_input'; Billrun_Factory::log()->log("Loading file " . $filename, Zend_Log::INFO); $billrun_end_time = Billrun_Util::getEndTime($billrun_key); $this->data = $subscriber->getListFromFile('files/' . $filename, $billrun_end_time); if (!count($this->data)) { Billrun_Factory::log()->log("No accounts were found for leftover aggregator", Zend_Log::ALERT); } if (is_array($this->data)) { $this->data = array_slice($this->data, $this->page * $this->size, $this->size, TRUE); } Billrun_Factory::log()->log("aggregator entities loaded: " . count($this->data), Zend_Log::INFO); Billrun_Factory::dispatcher()->trigger('afterAggregatorLoadData', array('aggregator' => $this)); }
/** * method to collect data which need to be handle by event */ public function handlerCollect($options) { if ($this->getName() != $options['type']) { return FALSE; } Billrun_Factory::log()->log("ILDS fraud collect handler triggered", Zend_Log::DEBUG); $lines = Billrun_Factory::db()->linesCollection(); $charge_time = Billrun_Util::getLastChargeTime(true, Billrun_Factory::config()->getConfigValue('ilds.billrun.charging_day', 20)); $base_match = array('$match' => array('source' => 'ilds')); $where = array('$match' => array('event_stamp' => array('$exists' => false), 'deposit_stamp' => array('$exists' => false), 'urt' => array('$gte' => new MongoDate($charge_time)), 'aprice' => array('$exists' => true), 'billrun' => array('$exists' => false))); $group = array('$group' => array("_id" => '$caller_phone_no', 'msisdn' => array('$first' => '$caller_phone_no'), "total" => array('$sum' => '$aprice'), 'lines_stamps' => array('$addToSet' => '$stamp'))); $project = array('$project' => array('caller_phone_no' => '$_id', '_id' => 0, 'msidsn' => 1, 'total' => 1, 'lines_stamps' => 1)); $having = array('$match' => array('total' => array('$gte' => floatval(Billrun_Factory::config()->getConfigValue('ilds.threshold', 100))))); $ret = $lines->aggregate($base_match, $where, $group, $project, $having); Billrun_Factory::log()->log("ILDS fraud plugin found " . count($ret) . " items", Zend_Log::DEBUG); return $ret; }
/** * method to log the processing * * @todo refactoring this method */ protected function logDB($fileData) { $log = Billrun_Factory::db()->logCollection(); Billrun_Factory::dispatcher()->trigger('beforeLogReceiveFile', array(&$fileData, $this)); $query = array('stamp' => $fileData['stamp'], 'received_time' => array('$exists' => false)); $addData = array('received_hostname' => Billrun_Util::getHostName(), 'received_time' => date(self::base_dateformat)); $update = array('$set' => array_merge($fileData, $addData)); if (empty($query['stamp'])) { Billrun_Factory::log()->log("Billrun_Receiver::logDB - got file with empty stamp : {$fileData['stamp']}", Zend_Log::NOTICE); return FALSE; } $result = $log->update($query, $update, array('w' => 1)); if ($result['ok'] != 1 || $result['n'] != 1) { Billrun_Factory::log()->log("Billrun_Receiver::logDB - Failed when trying to update a file log record " . $fileData['file_name'] . " with stamp of : {$fileData['stamp']}", Zend_Log::NOTICE); } return $result['n'] == 1 && $result['ok'] == 1; }
/** * method to clean account cache * * @param int $aid * * @return true on success, else false */ protected function cleanAccountCache($aid) { $cache = Billrun_Factory::cache(); if (empty($cache)) { return false; } $aids = array_unique(array_diff(Billrun_Util::verify_array(explode(',', $aid), 'int'), array(0))); $billrunKey = Billrun_Util::getBillrunKey(time()); $cachePrefix = 'balance_'; // this is not the action name because it's clear the balance cache foreach ($aids as $aid) { $cleanCacheKeys = array(Billrun_Util::generateArrayStamp(array_values(array('aid' => $aid, 'subscribers' => array(), 'stamp' => $billrunKey))), Billrun_Util::generateArrayStamp(array_values(array('aid' => $aid, 'subscribers' => null, 'stamp' => (int) $billrunKey))), Billrun_Util::generateArrayStamp(array_values(array('aid' => $aid, 'subscribers' => "", 'stamp' => (int) $billrunKey))), Billrun_Util::generateArrayStamp(array_values(array('aid' => $aid, 'subscribers' => 0, 'stamp' => (int) $billrunKey)))); foreach ($cleanCacheKeys as $cacheKey) { $cache->remove($cacheKey, $cachePrefix); } } return true; }
/** * Move the file to the workspace. * * @param string $srcPath The original file position * @param string $filename the filename * * @return mixed the new path if success, else false */ protected function handleFile($srcPath, $filename) { Billrun_Factory::log('Relocate receive handle file ' . $filename, Zend_Log::INFO); $srcPath = parent::handleFile($srcPath, $filename); Billrun_Factory::dispatcher()->trigger('beforeRelocateFileHandling', array($this, &$srcPath, $filename)); $newPath = $this->workspace . DIRECTORY_SEPARATOR . static::$type; if (!file_exists($newPath)) { mkdir($newPath, 0777, true); } $newPath .= DIRECTORY_SEPARATOR . $filename; $ret = $this->moveFiles ? copy($srcPath, $newPath) && unlink($srcPath) : copy($srcPath, $newPath); if ($this->preserve_timestamps) { $timestamp = filemtime($srcPath); Billrun_Util::setFileModificationTime($newPath, $timestamp); } Billrun_Factory::dispatcher()->trigger('afterRelocateFileHandling', array($this, &$srcPath, &$newPath, $filename, $ret)); return $ret ? $newPath : FALSE; }
public static function joinSubArraysOnKey($arrays, $depth = 1, $key = false) { if ($depth == 0 || !is_array($arrays)) { return $arrays; } // print_r($arrays); $retArr = array(); foreach ($arrays as $subKey => $subArray) { if ($key) { $retArr[$subKey] = array($key => Billrun_Util::joinSubArraysOnKey($subArray, $depth - 1, $subKey)); } else { $swappedArr = Billrun_Util::joinSubArraysOnKey($subArray, $depth - 1, $subKey); if (is_array($swappedArr)) { $retArr = array_merge_recursive($retArr, $swappedArr); } else { $retArr[$subKey] = $swappedArr; } } } return $retArr; }
/** * method to store and fetch by global cache layer * * @param type $params params to be used by cache to populate and store * * @return mixed the cached results */ protected function cache($params) { if (!isset($params['stampParams'])) { $params['stampParams'] = $params['fetchParams']; } $cache = Billrun_Factory::cache(); if (empty($cache)) { return $this->fetchData($params['fetchParams']); } $actionName = $this->getAction(); $cachePrefix = $this->getCachePrefix(); $cacheKey = Billrun_Util::generateArrayStamp(array_values($params['stampParams'])); $cachedData = $cache->get($cacheKey, $cachePrefix); if (empty($cachedData)) { $cachedData = $this->fetchData($params['fetchParams']); $lifetime = Billrun_Factory::config()->getConfigValue('api.cacheLifetime.' . $actionName, $this->getCacheLifeTime()); $cache->set($cacheKey, $cachedData, $cachePrefix, $lifetime); } else { Billrun_Factory::log()->log("Fetch data from cache for " . $actionName . " api call", Zend_Log::INFO); } return $cachedData; }
public function execute() { $request = $this->getRequest(); $aid = $request->get("aid"); Billrun_Factory::log()->log("Execute balance api call to " . $aid, Zend_Log::INFO); $stamp = Billrun_Util::getBillrunKey(time()); $subscribers = $request->get("subscribers"); if (!is_numeric($aid)) { return $this->setError("aid is not numeric", $request); } else { settype($aid, 'int'); } if (is_string($subscribers)) { $subscribers = explode(",", $subscribers); } else { $subscribers = array(); } $cacheParams = array('fetchParams' => array('aid' => $aid, 'subscribers' => $subscribers, 'stamp' => $stamp)); $output = $this->cache($cacheParams); header('Content-type: text/xml'); $this->getController()->setOutput(array($output, true)); // hack }
/** * @see Billrun_Calculator_Rate::getLineRate */ protected function getLineRate($row, $usage_type) { if ($this->shouldLineBeRated($row)) { $matchedRate = $this->rates['UNRATED']; $called_number = $this->extractNumber($row); $line_time = $row['urt']; $called_number_prefixes = Billrun_Util::getPrefixes($called_number); foreach ($called_number_prefixes as $prefix) { if (isset($this->rates[$prefix])) { foreach ($this->rates[$prefix] as $rate) { if (isset($rate['rates'][$usage_type]) && (!isset($rate['params']['fullEqual']) || $prefix == $called_number)) { if ($rate['from'] <= $line_time && $rate['to'] >= $line_time) { $matchedRate = $rate; break 2; } } } } } return $matchedRate; } else { return false; } }
public function execute() { Billrun_Factory::log()->log("Execute recreate invoices", Zend_Log::INFO); $request = $this->getRequest()->getRequest(); // supports GET / POST requests if (empty($request['account_id'])) { return $this->setError('Please supply at least one account id', $request); } $billrun_key = Billrun_Util::getPreviousBillrunKey(Billrun_Util::getBillrunKey(time())); // Warning: will convert half numeric strings / floats to integers $account_ids = array_unique(array_diff(Billrun_Util::verify_array(explode(',', $request['account_id']), 'int'), array(0))); if ($account_ids) { $options = array('autoload' => 0, 'stamp' => $billrun_key); $customer_aggregator_options = array('override_accounts' => $account_ids, 'bulk_account_preload' => 0); $customerOptions = array('type' => 'customer', 'aggregator' => $customer_aggregator_options); $customerAgg = Billrun_Aggregator::getInstance(array_merge($options, $customerOptions)); $customerAgg->load(); $successfulAccounts = $customerAgg->aggregate(); } else { return $this->setError('Illegal aids', $request); } $this->getController()->setOutput(array(array('status' => 1, 'desc' => 'success', 'input' => $request, 'successfulAccounts' => $successfulAccounts))); return TRUE; }
/** * mark a file in the log collection as being processed and return it * @return Mongodloid_Entity the file to process on sucessful update false otherwise */ protected function getFileForProcessing() { $log = Billrun_Factory::db()->logCollection(); $adoptThreshold = strtotime('-' . $this->orphandFilesAdoptionTime); // verify minimum orphan time to avoid parallel processing if (Billrun_Factory::config()->isProd() && time() - $adoptThreshold < 3600) { Billrun_Factory::log()->log("Processor orphan time less than one hour: " . $this->orphandFilesAdoptionTime . ". Please set value greater than or equal to one hour. We will take one hour for now", Zend_Log::NOTICE); $adoptThreshold = time() - 3600; } $query = array('source' => static::$type, 'process_time' => array('$exists' => false), '$or' => array(array('start_process_time' => array('$exists' => false)), array('start_process_time' => array('$lt' => new MongoDate($adoptThreshold)))), 'received_time' => array('$exists' => true)); $update = array('$set' => array('start_process_time' => new MongoDate(time()), 'start_process_host' => Billrun_Util::getHostName())); $options = array('sort' => array('received_time' => 1), 'new' => true); $file = $log->findAndModify($query, $update, array(), $options); $file->collection($log); return $file; }
protected function buildData($line, $line_number = null) { $row = parent::buildData($line, $line_number); if (isset($row[$this->structConfig['config']['date_field']])) { if ($row['type'] == 'mmsc') { $datetime = DateTime::createFromFormat($this->structConfig['config']['date_format'], preg_replace('/^(\\d+)\\+(\\d)$/', '$1+0$2:00', $row[$this->structConfig['config']['date_field']])); $matches = array(); if (preg_match("/^\\+*(\\d+)\\//", $row['recipent_addr'], $matches)) { $row['called_number'] = $matches[1]; } } else { if (isset($row[$this->structConfig['config']['date_field']])) { $offset = (isset($this->structConfig['config']['date_offset']) && isset($row[$this->structConfig['config']['date_offset']]) ? ($row[$this->structConfig['config']['date_offset']] > 0 ? "+" : "") . $row[$this->structConfig['config']['date_offset']] : "00") . ':00'; $datetime = DateTime::createFromFormat($this->structConfig['config']['date_format'], $row[$this->structConfig['config']['date_field']] . $offset); } } if (isset($row[$this->structConfig['config']['calling_number_field']])) { $row[$this->structConfig['config']['calling_number_field']] = Billrun_Util::msisdn($row[$this->structConfig['config']['calling_number_field']]); } if (isset($row[$this->structConfig['config']['called_number_field']])) { $row[$this->structConfig['config']['called_number_field']] = Billrun_Util::msisdn($row[$this->structConfig['config']['called_number_field']]); } $row['urt'] = new MongoDate($datetime->format('U')); } return $row; }
/** * Removes lines from queue, reset added fields off lines and re-insert to queue first stage * @todo support update/removal of credit lines */ protected function resetLines() { $lines_coll = Billrun_Factory::db()->linesCollection(); $queue_coll = Billrun_Factory::db()->queueCollection(); if (!empty($this->sids) && !empty($this->billrun_key)) { $offset = 0; while ($update_count = count($update_sids = array_slice($this->sids, $offset, 10))) { Billrun_Factory::log()->log('Resetting lines of subscribers ' . implode(',', $update_sids), Zend_Log::INFO); $query = array('$or' => array(array('billrun' => $this->billrun_key), array('billrun' => array('$exists' => FALSE), 'urt' => array('$gte' => new MongoDate(Billrun_Util::getStartTime($this->billrun_key)), '$lte' => new MongoDate(Billrun_Util::getEndTime($this->billrun_key))))), 'sid' => array('$in' => $update_sids), 'type' => array('$ne' => 'credit'), 'process_time' => array('$lt' => date(Billrun_Base::base_dateformat, strtotime($this->process_time_offset . ' ago')))); $lines = $lines_coll->query($query); $stamps = array(); $queue_lines = array(); foreach ($lines as $line) { $stamps[] = $line['stamp']; $queue_line = array('calc_name' => false, 'calc_time' => false, 'stamp' => $line['stamp'], 'type' => $line['type'], 'urt' => $line['urt'], 'skip_fraud' => true); // todo: refactoring $advancedProperties = Billrun_Factory::config()->getConfigValue("queue.advancedProperties", array('imsi', 'msisdn', 'called_number', 'calling_number')); foreach ($advancedProperties as $property) { if (isset($line[$property]) && !isset($queue_line[$property])) { $queue_line[$property] = $line[$property]; } } $queue_lines[] = $queue_line; } $stamps_query = array('stamp' => array('$in' => $stamps)); $update = array('$unset' => array('apr' => 1, 'aprice' => 1, 'arate' => 1, 'arategroup' => 1, 'billrun' => 1, 'in_arate' => 1, 'in_group' => 1, 'in_plan' => 1, 'out_plan' => 1, 'over_arate' => 1, 'over_group' => 1, 'over_plan' => 1, 'plan' => 1, 'usagesb' => 1, 'usagev' => 1), '$set' => array('rebalance' => new MongoDate())); if ($stamps) { $ret = $queue_coll->remove($stamps_query, array('w' => 1)); // ok == 1, err null if (isset($ret['err']) && !is_null($ret['err'])) { return FALSE; } else { $ret = $this->resetBalances($update_sids); // err null if (isset($ret['err']) && !is_null($ret['err'])) { return FALSE; } else { if (Billrun_Factory::db()->compareServerVersion('2.6', '>=') === true) { $ret = $queue_coll->batchInsert($queue_lines, array('w' => 1)); // ok==true, nInserted==0 if w was 0 if (isset($ret['err']) && !is_null($ret['err'])) { return FALSE; } } else { foreach ($queue_lines as $qline) { $ret = $queue_coll->insert($qline, array('w' => 1)); // ok==1, err null if (isset($ret['err']) && !is_null($ret['err'])) { return FALSE; } } } $ret = $lines_coll->update($stamps_query, $update, array('multiple' => 1, 'w' => 1)); // err null if (isset($ret['err']) && !is_null($ret['err'])) { return FALSE; } } } } $offset += 10; } } return TRUE; }
/** * @see Billrun_Plugin_Interface_IParser::parseData */ public function parseData($type, $line, Billrun_Parser &$parser) { if ($type != $this->getName()) { return FALSE; } $data = array(); $offset = 0; $data['record_length'] = $this->parseField(substr($line, $offset, 2), array('decimal' => 2)); $offset += 2; $data['record_type'] = $this->parseField(substr($line, $offset, 1), array('bcd_encode' => 1)); $offset += 1; //Billrun_Factory::log()->log("Record_type : {$data['record_type']}",Zend_log::DEBUG); if (isset($this->nsnConfig[$data['record_type']])) { foreach ($this->nsnConfig[$data['record_type']] as $key => $fieldDesc) { if ($fieldDesc) { if (isset($this->nsnConfig['fields'][$fieldDesc])) { $length = intval(current($this->nsnConfig['fields'][$fieldDesc]), 10); $data[$key] = $this->parseField(substr($line, $offset, $length), $this->nsnConfig['fields'][$fieldDesc]); /* if($data['record_type'] == "12") {//DEBUG... Billrun_Factory::log()->log("Data $key : {$data[$key]} , offset: ". dechex($offset),Zend_log::DEBUG); } */ $offset += $length; } else { throw new Exception("Nsn:parse - Couldn't find field: {$fieldDesc} "); } } } $data['urt'] = new MongoDate(Billrun_Util::dateTimeConvertShortToIso((string) (isset($data['charging_start_time']) && $data['charging_start_time'] ? $data['charging_start_time'] : $data['call_reference_time']), date("P", strtotime($data['call_reference_time'])))); } //Use the actual charing time duration instead of the duration that was set by the switch if (isset($data['duration'])) { $data['org_dur'] = $data['duration']; // save the original duration. } if (isset($data['charging_end_time']) && isset($data['charging_start_time']) && (strtotime($data['charging_end_time']) > 0 && strtotime($data['charging_start_time']) > 0)) { $data['duration'] = strtotime($data['charging_end_time']) - strtotime($data['charging_start_time']); } //Remove the "10" in front of the national call with an international prefix // if (isset($data['in_circuit_group_name']) && preg_match("/^RCEL/", $data['in_circuit_group_name']) && strlen($data['called_number']) > 10 && substr($data['called_number'], 0, 2) == "10") { // will fail when in_circuit_group_name is empty / called_number length is exactly 10 if (isset($data['out_circuit_group']) && in_array($data['out_circuit_group'], array('2100', '2101', '2499')) && substr($data['called_number'], 0, 2) == "10") { $data['called_number'] = substr($data['called_number'], 2); } else { if (in_array($data['record_type'], array('30', '31')) && preg_match($this->ild_called_number_regex, $data['called_number'])) { $data['ild_prefix'] = substr($data['called_number'], 0, 3); $data['called_number'] = substr($data['called_number'], 3); } } $parser->setLastParseLength($data['record_length']); //@TODO add unifiom field translation. ('record_opening_time',etc...) return isset($this->nsnConfig[$data['record_type']]) ? $data : false; }
/** * method to parse the data */ protected function parse() { if (!is_resource($this->fileHandler)) { Billrun_Factory::log()->log("Resource is not configured well", Zend_Log::ERR); return false; } while ($line = fgets($this->fileHandler)) { $record_type = $this->getLineType($line); // @todo: convert each case code snippet to protected method (including triggers) switch ($record_type) { case 'H': // header if (isset($this->data['header'])) { Billrun_Factory::log()->log("double header", Zend_Log::ERR); return false; } $this->parser->setStructure($this->header_structure); $this->parser->setLine($line); // @todo: trigger after header load (including $header) $header = $this->parser->parse(); // @todo: trigger after header parse (including $header) $header['source'] = self::$type; $header['type'] = static::$type; $header['file'] = basename($this->filePath); $header['process_time'] = date(self::base_dateformat); $this->data['header'] = $header; break; case 'T': //trailer if (isset($this->data['trailer'])) { Billrun_Factory::log()->log("double trailer", Zend_Log::ERR); return false; } $this->parser->setStructure($this->trailer_structure); $this->parser->setLine($line); // @todo: trigger after trailer load (including $header, $data, $trailer) $trailer = $this->parser->parse(); // @todo: trigger after trailer parse (including $header, $data, $trailer) $trailer['source'] = self::$type; $trailer['type'] = static::$type; $trailer['header_stamp'] = $this->data['header']['stamp']; $trailer['file'] = basename($this->filePath); $trailer['process_time'] = date(self::base_dateformat); $this->data['trailer'] = $trailer; break; case 'D': //data if (!isset($this->data['header'])) { Billrun_Factory::log()->log("No header found", Zend_Log::ERR); return false; } $this->parser->setStructure($this->data_structure); // for the next iteration $this->parser->setLine($line); // @todo: trigger after row load (including $header, $row) $row = $this->parser->parse(); // @todo: trigger after row parse (including $header, $row) $row['source'] = self::$type; $row['type'] = static::$type; $row['log_stamp'] = $this->getFileStamp(); $row['file'] = basename($this->filePath); $row['process_time'] = date(self::base_dateformat); $row['urt'] = new MongoDate(Billrun_Util::dateTimeConvertShortToIso($row['call_start_dt'], $this->defTimeOffset)); // hot fix cause this field contain iso-8859-8 if (isset($row['country_desc'])) { $row['country_desc'] = mb_convert_encoding($row['country_desc'], 'UTF-8', 'ISO-8859-8'); } if ($this->isValidDataRecord($row)) { $this->data['data'][] = $row; } break; default: //raise warning break; } } return true; }
/** * @see Billrun_Calculator_Rate::getLineRate */ protected function getLineRate($row, $usage_type) { $line_time = $row['urt']; $serving_network = $row['serving_network']; $sender = isset($row['sending_source']) ? $row['sending_source'] : false; $matchedRate = false; $prefix_length_matched = 0; if (!is_null($serving_network)) { $call_number = $this->number_to_rate($row); if ($call_number) { $call_number = preg_replace("/^[^1-9]*/", "", $call_number); $call_number_prefixes = Billrun_Util::getPrefixes($call_number); } $potential_rates = array(); if (isset($this->rates['by_names'][$serving_network])) { foreach ($this->rates['by_names'][$serving_network] as $named_rate) { if (is_array($named_rate['params']['sending_sources'])) { if (!$sender || isset($named_rate['params']['sending_sources']) && in_array($sender, $named_rate['params']['sending_sources'])) { $potential_rates[] = $named_rate; } } else { if (is_string($named_rate['params']['sending_sources'])) { if (!$sender || isset($named_rate['params']['sending_sources']) && preg_match($named_rate['params']['sending_sources'], $sender)) { $potential_rates[] = $named_rate; } } } } } if (!empty($this->rates['by_regex'])) { foreach ($this->rates['by_regex'] as $regex => $regex_rates) { if (preg_match($regex, $serving_network)) { foreach ($regex_rates as $regex_rate) { if (is_array($regex_rate['params']['sending_sources'])) { if (!$sender || isset($regex_rate['params']['sending_sources']) && in_array($sender, $regex_rate['params']['sending_sources'])) { $potential_rates[] = $regex_rate; } } else { if (is_string($regex_rate['params']['sending_sources'])) { if (!$sender || isset($regex_rate['params']['sending_sources']) && preg_match($regex_rate['params']['sending_sources'], $sender)) { $potential_rates[] = $regex_rate; } } } } } } } foreach ($potential_rates as $rate) { if (isset($rate['rates'][$usage_type])) { if ($rate['from'] <= $line_time && $rate['to'] >= $line_time) { if (!$matchedRate && empty($rate['params']['prefix']) || is_array($rate['params']['serving_networks']) && !$prefix_length_matched) { // array of serving networks is stronger then regex of serving_networks $matchedRate = $rate; } if (isset($call_number_prefixes) && !empty($rate['params']['prefix'])) { if (!isset($rate['params']['fullEqual'])) { foreach ($call_number_prefixes as $prefix) { if (in_array($prefix, $rate['params']['prefix']) && strlen($prefix) > $prefix_length_matched) { $prefix_length_matched = strlen($prefix); $matchedRate = $rate; } } } else { if (in_array($call_number, $rate['params']['prefix']) && strlen($call_number) > $prefix_length_matched) { $prefix_length_matched = strlen($call_number); $matchedRate = $rate; } } } } } } } if ($matchedRate === FALSE && !in_array($usage_type, $this->optional_usage_types)) { $matchedRate = $this->rates['UNRATED']; } return $matchedRate; }
public function beforeCommitSubscriberBalance(&$row, &$pricingData, &$query, &$update, $arate, $calculator) { if ($arate['key'] == 'INTERNET_VF') { if (isset($pricingData['arategroup']) && $pricingData['arategroup'] == 'VF_INCLUDED') { $query = array('sid' => $query['sid'], 'billrun_month' => $query['billrun_month']); $pricingData = array('arategroup' => $pricingData['arategroup'], 'usagesb' => $pricingData['usagesb']); $update['$set'] = array('tx.' . $row['stamp'] => $pricingData); foreach (array_keys($update['$inc']) as $key) { if (!Billrun_Util::startsWith($key, 'balance.groups')) { unset($update['$inc'][$key]); } } } else { $pricingData = $update = array(); } } }