public function afterDataParsing(&$row, $parser) { if ($parser->getType() == 'nrtrde') { // make the duration rounded by minute if (isset($row['callEventDuration'])) { $callEventDuration = $row['callEventDuration']; $row['callEventDurationRound'] = ceil($callEventDuration / 60) * 60; } // add record opening time UTC aligned if (isset($row['callEventStartTimeStamp'])) { $row['urt'] = new MongoDate(Billrun_Util::dateTimeConvertShortToIso($row['callEventStartTimeStamp'], $row['utcTimeOffset'])); } } }
/** * @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; }
/** * Pull required fields from the CDR nested tree to the surface. * @param type $cdrLine the line to monipulate. */ protected function surfaceCDRFields(&$cdrLine, $mapping) { foreach ($mapping as $key => $fieldToMap) { $val = Billrun_Util::getNestedArrayVal($cdrLine, $fieldToMap, null); if ($val !== null && Billrun_Util::getFieldVal($this->tap3Config['fields_to_save'][$key], false)) { $cdrLine[$key] = $val; } } if (Billrun_Util::getNestedArrayVal($cdrLine, $mapping['localTimeStamp']) !== null) { $offset = $this->currentFileHeader['networkInfo']['UtcTimeOffsetInfoList'][Billrun_Util::getNestedArrayVal($cdrLine, $mapping['TimeOffsetCode'])]; $cdrLine['urt'] = new MongoDate(Billrun_Util::dateTimeConvertShortToIso(Billrun_Util::getNestedArrayVal($cdrLine, $mapping['localTimeStamp']), $offset)); $cdrLine['tzoffset'] = $offset; } if (Billrun_Util::getNestedArrayVal($cdrLine, $mapping['tele_srv_code']) !== null && isset($cdrLine['record_type'])) { $tele_service_code = Billrun_Util::getNestedArrayVal($cdrLine, $mapping['tele_srv_code']); $record_type = $cdrLine['record_type']; if ($record_type == '9') { if ($tele_service_code == '11') { if (Billrun_Util::getNestedArrayVal($cdrLine, $mapping['dialed_digits'])) { $cdrLine['called_number'] = Billrun_Util::getNestedArrayVal($cdrLine, $mapping['dialed_digits']); } else { $cdrLine['called_number'] = Billrun_Util::getNestedArrayVal($cdrLine, $mapping['called_number']); //$cdrLine['basicCallInformation']['Desination']['CalledNumber']; } } else { if ($tele_service_code == '22') { if (Billrun_Util::getNestedArrayVal($cdrLine, $mapping['dialed_digits'])) { $cdrLine['called_number'] = Billrun_Util::getNestedArrayVal($cdrLine, $mapping['dialed_digits']); } else { if (isset($cdrLine['basicCallInformation']['Desination']['CalledNumber'])) { // @todo check with sefi. reference: db.lines.count({'BasicServiceUsedList.BasicServiceUsed.BasicService.BasicServiceCode.TeleServiceCode':"22",record_type:'9','basicCallInformation.Desination.DialedDigits':{$exists:false}});) $cdrLine['called_number'] = Billrun_Util::getNestedArrayVal($cdrLine, $mapping['called_number']); } } } } } else { if ($record_type == 'a') { if ($tele_service_code == '11') { if (Billrun_Util::getNestedArrayVal($cdrLine, $mapping['called_number'])) { $cdrLine['called_number'] = Billrun_Util::getNestedArrayVal($cdrLine, $mapping['called_number']); //$cdrLine['basicCallInformation']['Desination']['CalledNumber']; } } } } } if (isset($cdrLine['called_number'])) { $cdrLine['called_number'] = Billrun_Util::msisdn($cdrLine['called_number']); } // if (!Billrun_Util::getNestedArrayVal($cdrLine, $mapping['calling_number']) && isset($tele_service_code) && isset($record_type) ) { // if ($record_type == 'a' && ($tele_service_code == '11' || $tele_service_code == '21')) { // if (Billrun_Util::getNestedArrayVal($cdrLine, $mapping['call_org_number'])) { // for some calls (incoming?) there's no calling number // $cdrLine['calling_number'] = Billrun_Util::getNestedArrayVal($cdrLine, $mapping['call_org_number']); // } // } // } if (Billrun_Util::getNestedArrayVal($cdrLine, $mapping['serving_network']) !== null) { $cdrLine['serving_network'] = Billrun_Util::getNestedArrayVal($cdrLine, $mapping['serving_network']); } else { $cdrLine['serving_network'] = $this->currentFileHeader['header']['sending_source']; } if (Billrun_Util::getNestedArrayVal($cdrLine, $mapping['sdr']) !== null) { $sdrs = Billrun_Util::getNestedArrayVal($cdrLine, $mapping['sdr'], null, TRUE); $sum = $this->sumup_arrays($sdrs, 20); $cdrLine['sdr'] = $sum; $cdrLine['exchange_rate'] = $this->exchangeRates[Billrun_Util::getNestedArrayVal($cdrLine, $mapping['exchange_rate_code'], 0)]; } if (Billrun_Util::getNestedArrayVal($cdrLine, $mapping['sdr_tax']) !== null) { $cdrLine['sdr_tax'] = Billrun_Util::getNestedArrayVal($cdrLine, $mapping['sdr_tax']) / $this->sdr_division_value; } //save the sending source in each of the lines $cdrLine['sending_source'] = $this->currentFileHeader['header']['sending_source']; }
/** * @see Billrun_Plugin_Interface_IParser::parseData */ public function parseData($type, $data, \Billrun_Parser &$parser) { if ($this->getName() != $type) { return FALSE; } $asnObject = Asn_Base::parseASNString($data); $parser->setLastParseLength($asnObject->getDataLength() + self::RECORD_PADDING); $type = $asnObject->getType(); $cdrLine = false; if (isset($this->ggsnConfig[$type])) { $cdrLine = $this->getASNDataByConfig($asnObject, $this->ggsnConfig[$type], $this->ggsnConfig['fields']); if ($cdrLine && !isset($cdrLine['record_type'])) { $cdrLine['record_type'] = $type; } //convert to unified time GMT time. $timeOffset = isset($cdrLine['ms_timezone']) ? $cdrLine['ms_timezone'] : date('P'); $cdrLine['urt'] = new MongoDate(Billrun_Util::dateTimeConvertShortToIso($cdrLine['record_opening_time'], $timeOffset)); if (is_array($cdrLine['rating_group'])) { $fbc_uplink_volume = $fbc_downlink_volume = 0; $cdrLine['org_fbc_uplink_volume'] = $cdrLine['fbc_uplink_volume']; $cdrLine['org_fbc_downlink_volume'] = $cdrLine['fbc_downlink_volume']; $cdrLine['org_rating_group'] = $cdrLine['rating_group']; foreach ($cdrLine['rating_group'] as $key => $rateVal) { if (isset($this->ggsnConfig['rating_groups'][$rateVal])) { $fbc_uplink_volume += $cdrLine['fbc_uplink_volume'][$key]; $fbc_downlink_volume += $cdrLine['fbc_downlink_volume'][$key]; } } $cdrLine['fbc_uplink_volume'] = $fbc_uplink_volume; $cdrLine['fbc_downlink_volume'] = $fbc_downlink_volume; $cdrLine['rating_group'] = 0; } else { if ($cdrLine['rating_group'] == 10) { return false; } } } else { Billrun_Factory::log()->log("couldn't find definition for {$type}", Zend_Log::INFO); } //Billrun_Factory::log()->log($asnObject->getType() . " : " . print_r($cdrLine,1) , Zend_Log::DEBUG); return $cdrLine; }
/** * Pull required fields from the CDR nested tree to the surface. * @param type $cdrLine the line to monipulate. */ protected function surfaceCDRFields(&$cdrLine) { if (isset($cdrLine['basicCallInformation']['CallEventStartTimeStamp']['localTimeStamp'])) { $offset = $this->currentFileHeader['networkInfo']['UtcTimeOffsetInfoList'][$cdrLine['basicCallInformation']['CallEventStartTimeStamp']['TimeOffsetCode']]; $cdrLine['urt'] = new MongoDate(Billrun_Util::dateTimeConvertShortToIso($cdrLine['basicCallInformation']['CallEventStartTimeStamp']['localTimeStamp'], $offset)); $cdrLine['tzoffset'] = $offset; } if (isset($cdrLine['basicCallInformation']['chargeableSubscriber']['simChargeableSubscriber']['imsi'])) { $cdrLine['imsi'] = $cdrLine['basicCallInformation']['chargeableSubscriber']['simChargeableSubscriber']['imsi']; } if (isset($cdrLine['basicCallInformation']['GprsChargeableSubscriber']['chargeableSubscriber']['simChargeableSubscriber']['imsi'])) { $cdrLine['imsi'] = $cdrLine['basicCallInformation']['GprsChargeableSubscriber']['chargeableSubscriber']['simChargeableSubscriber']['imsi']; } if (isset($cdrLine['BasicServiceUsedList']['BasicServiceUsed']['BasicService']['BasicServiceCode']['TeleServiceCode']) && isset($cdrLine['record_type'])) { $tele_service_code = $cdrLine['BasicServiceUsedList']['BasicServiceUsed']['BasicService']['BasicServiceCode']['TeleServiceCode']; $record_type = $cdrLine['record_type']; if ($record_type == '9') { if ($tele_service_code == '11') { $cdrLine['called_number'] = $cdrLine['basicCallInformation']['Desination']['CalledNumber']; } else { if ($tele_service_code == '22') { if (isset($cdrLine['basicCallInformation']['Desination']['DialedDigits'])) { $cdrLine['called_number'] = $cdrLine['basicCallInformation']['Desination']['DialedDigits']; } else { if (isset($cdrLine['basicCallInformation']['Desination']['CalledNumber'])) { // @todo check with sefi. reference: db.lines.count({'BasicServiceUsedList.BasicServiceUsed.BasicService.BasicServiceCode.TeleServiceCode':"22",record_type:'9','basicCallInformation.Desination.DialedDigits':{$exists:false}});) $cdrLine['called_number'] = $cdrLine['basicCallInformation']['Desination']['CalledNumber']; } } } } } } if (isset($cdrLine['basicCallInformation']['GprsChargeableSubscriber']['chargeableSubscriber']['simChargeableSubscriber']['msisdn'])) { $cdrLine['calling_number'] = $cdrLine['basicCallInformation']['GprsChargeableSubscriber']['chargeableSubscriber']['simChargeableSubscriber']['msisdn']; } else { if (isset($cdrLine['basicCallInformation']['chargeableSubscriber']['simChargeableSubscriber']['msisdn'])) { $cdrLine['calling_number'] = $cdrLine['basicCallInformation']['chargeableSubscriber']['simChargeableSubscriber']['msisdn']; } else { if (isset($cdrLine['BasicServiceUsedList']['BasicServiceUsed']['BasicService']['BasicServiceCode']['TeleServiceCode']) && isset($cdrLine['record_type'])) { if ($record_type == 'a' && ($tele_service_code == '11' || $tele_service_code == '21')) { if (isset($cdrLine['basicCallInformation']['callOriginator']['callingNumber'])) { // for some calls (incoming?) there's no calling number $cdrLine['calling_number'] = $cdrLine['basicCallInformation']['callOriginator']['callingNumber']; } } } } } if (isset($cdrLine['LocationInformation']['GeographicalLocation']['ServingNetwork'])) { $cdrLine['serving_network'] = $cdrLine['LocationInformation']['GeographicalLocation']['ServingNetwork']; } else { $cdrLine['serving_network'] = $this->currentFileHeader['header']['sending_source']; } }