|
<?php defined('SYSPATH') or die('No direct script access.');
|
|
/*
|
|
* This file is part of open source system FreenetIS
|
|
* and it is released under GPLv3 licence.
|
|
*
|
|
* More info about licence can be found:
|
|
* http://www.gnu.org/licenses/gpl-3.0.html
|
|
*
|
|
* More info about project can be found:
|
|
* http://www.freenetis.org/
|
|
*
|
|
*/
|
|
|
|
define("PVI_MODELS_PATH", APPPATH . "libraries/parser_vodafone_invoice_models");
|
|
|
|
require_once PVI_MODELS_PATH . "/Bill_Data.php";
|
|
require_once PVI_MODELS_PATH . "/Services.php";
|
|
require_once PVI_MODELS_PATH . "/Call_Service.php";
|
|
require_once PVI_MODELS_PATH . "/Sms_Service.php";
|
|
require_once PVI_MODELS_PATH . "/Internet_Service.php";
|
|
require_once PVI_MODELS_PATH . "/Vpn_Call_Service.php";
|
|
require_once PVI_MODELS_PATH . "/Fixed_Call_Service.php";
|
|
require_once PVI_MODELS_PATH . "/Pay_Service.php";
|
|
require_once PVI_MODELS_PATH . "/RoamingSms_Service.php";
|
|
|
|
|
|
/**
|
|
* Parser_Vodafone_Invoice je parser faktur telefoního operátora Vodafone.
|
|
* Faktury Vodafone jsou ukládány v PDF, na které nelze užít unixových utilit pdfto*
|
|
* Tento parser zpracovává vstup z programu Adobe Reader. Zkopírovaný uživatelem
|
|
* pomocí CTRL+A.
|
|
*
|
|
* Cílem parseru je získat informace o faktuře, fakturovaných telefoních číslech
|
|
* a o službách které byly číslům poskytnuty.
|
|
*
|
|
* TENTO PARSER JE POUŽÍVÁN NA FAKTURY OD DATA 09.2011 VČETNĚ, KDY PROBĚHLA ZMĚNA
|
|
* FORMÁTU FAKTUR.
|
|
*
|
|
* @author Ondřej Fibich - ondrej.fibich(at)gmail(dot)com
|
|
* @version 1.1
|
|
*/
|
|
class Parser_Phone_Invoice_Vodafone2 extends Parser_Phone_Invoice
|
|
{
|
|
// Konstanty pro hlavičku faktury -->
|
|
const BILL_INFO_STARTER = "èíslo úètu kód banky variabilní symbol specifický symbol vystavení";
|
|
const BILL_INFO_REGEX = "^([0-9]+) ([0-9]+) ([0-9]+) ([0-9]+) ([0-9]{2})\.([0-9]{2})\.([0-9]{4})$";
|
|
const BILL_INFO_PRICE_REGEX = "^Celkový základ DPH ([0-9]+) *%([0-9\, ]+)$";
|
|
const BILL_INFO_DPH_REGEX = "^Celkem DPH ([0-9]+) *%([0-9\, ]+)$";
|
|
const BILL_INFO_PERIOD_REGEX = "^Zúètovací období ([0-9]{2})\.([0-9]{2})\.([0-9]{4}) \- ([0-9]{2})\.([0-9]{2})\.([0-9]{4})$";
|
|
const BILL_INFO_NUMBERS_COUNT_REGEX = "^Poèet telefonních èísel ([0-9]+)$";
|
|
|
|
const BILL_EXTRACT_START_FL = "Podrobné vyúètování";
|
|
|
|
public static $BILL_EXTRACT_START_SL = array
|
|
(
|
|
"p=pièka, Mp=mimo pièku, Vkn=víkend, +=hovor probìhl ve více obdobích",
|
|
"Šp=špicka, MŠp=mimo špicku, Vkn=víkend, +=hovor probehl ve více obdobích"
|
|
);
|
|
// <-- Konstanty prohlavičku faktury
|
|
|
|
const BILL_EXTRACT_DATA_LONG_CONNECTIONS = "^(Pøipojení na dlouho[^\(]*)\(([0-9]{2}).([0-9]{2}).([0-9]{4}) ([0-9]{2}):([0-9]{2})\) [0-9]+ ([0-9\, ]+) ([0-9]+) %";
|
|
const BILL_EXTRACT_DATA_DAY_CONNECTIONS = "^(Internet v mobilu na den) ([0-9]+) ([0-9\, ]+) ([0-9]+) % ([0-9\, ]+)$";
|
|
|
|
// Konstanty pro podrobný výpis -->
|
|
const BILL_EXTRACT_PHONE_REGEX = "^Telefonní èíslo ([0-9]{3} [0-9]{3} [0-9]{3})( Tarif)?";
|
|
// <-- Konstanty pro podrobný výpis
|
|
|
|
/** Jméno pole v Services reprezentující dané služby */
|
|
const SERVICE_ARRAY = 0;
|
|
/** První řádek služby v poli $BILL_EXTRACT_SERVICES */
|
|
const FLINE = 1;
|
|
/** Druhý řádek služby v poli $BILL_EXTRACT_SERVICES */
|
|
const SLINE = 2;
|
|
/** Datový řádek služby v poli $BILL_EXTRACT_SERVICES */
|
|
const REGEX = 3;
|
|
/** Počet datových položek datového řádku služby v poli $BILL_EXTRACT_SERVICES */
|
|
const REGEX_COUNT = 4;
|
|
/** Patička tabulky v poli $BILL_EXTRACT_SERVICES */
|
|
const LLINE = 5;
|
|
|
|
/**
|
|
* Pole parsovacích informací o službách.
|
|
* Obsahuje pole o informaci o službě, ve kterém se v tomto pořadí nachází údaje:
|
|
* První řádek pro zjištění služny; Druhý; Regulární výraz datového řádku;
|
|
* Počet datových položek; Regulární výraz patičky.
|
|
* @var array
|
|
*/
|
|
protected static $BILL_EXTRACT_SERVICES = array
|
|
(
|
|
"call" => array
|
|
(
|
|
"calls", "Hlasové sluby",
|
|
"voice Datum Èas Volané èíslo Trvání Popis Sleva Volné minuty Kè bez DPH",
|
|
// den, měsíc, hodina, minuta, sekunda, číslo, trvání, popis, sleva, ?cena?
|
|
"^voice ([0-9]{1,2}).([0-9]{1,2}). ([0-9]{2}):([0-9]{2}):([0-9]{2}) ([+*]*[0-9]+[+*/]*[0-9]*) ([0-9]{2}:[0-9]{2}:[0-9]{2}) (.*?) \-?([0-9]+,[0-9]{2})([0-9 ]+,[0-9]{2})?$",
|
|
10,
|
|
"Celkem za Hlasové sluby [0-9]{2}:[0-9]{2}:[0-9]{2} ([0-9 ]+,[0-9]{2})([0-9 ]+,[0-9]{2})?"
|
|
),
|
|
"roaming_call" => array
|
|
(
|
|
"calls", "Roaming - hlasové sluby",
|
|
"Datum Èas Volané/Pøijaté èíslo Trvání Popis Sleva Volné minuty Kè bez DPH",
|
|
// den, měsíc, hodina, minuta, sekunda, číslo, trvání, popis, sleva, ?cena?
|
|
"^([0-9]{1,2}).([0-9]{1,2}). ([0-9]{2}):([0-9]{2}):([0-9]{2}) ([+*]*[0-9]+[+*/]*[0-9]*) ([0-9]{2}:[0-9]{2}:[0-9]{2}) (.*?) ([0-9]+,[0-9]{2})([0-9 ]+,[0-9]{2})?$",
|
|
10,
|
|
"Celkem za Roaming - hlasové sluby [0-9]{2}:[0-9]{2}:[0-9]{2} ([0-9 ]+,[0-9]{2})([0-9 ]+,[0-9]{2})?"
|
|
),
|
|
"sms" => array
|
|
(
|
|
"smss", "SMS sluby",
|
|
"sms Datum Èas Volané èíslo Popis Sleva Volné SMS Kè bez DPH",
|
|
// den, měsíc, hodina, minuta, sekunda, číslo, popis, sleva, ?cena?
|
|
"^sms ([0-9]{1,2}).([0-9]{1,2}). ([0-9]{2}):([0-9]{2}):([0-9]{2}) ([+*]*[0-9]+[+*/]*[0-9]*) (.*?) \-?([0-9]+,[0-9]{2})([0-9 ]+,[0-9]{2})?$",
|
|
9,
|
|
"Celkem za SMS sluby ([0-9 ]+,[0-9]{2})"
|
|
),
|
|
"mms" => array
|
|
(
|
|
"smss", "MMS sluby",
|
|
"sms Datum Èas Volané èíslo Popis Sleva Volné MMS Kè bez DPH",
|
|
// den, měsíc, hodina, minuta, sekunda, číslo, popis, sleva, ?cena?
|
|
"^sms ([0-9]{1,2}).([0-9]{1,2}). ([0-9]{2}):([0-9]{2}):([0-9]{2}) ([+*]*[0-9]+[+*/]*[0-9]*) (.*?) \-?([0-9]+,[0-9]{2})([0-9 ]+,[0-9]{2})?$",
|
|
9,
|
|
"Celkem za MMS sluby ([0-9 ]+,[0-9]{2})"
|
|
),
|
|
"roaming_sms" => array
|
|
(
|
|
"roaming_smss", "Roaming - SMS",
|
|
"sms Datum Èas Volané èíslo Popis Sleva Volné SMS Kè bez DPH",
|
|
// den, měsíc, hodina, minuta, sekunda, číslo, popis, sleva, ?cena?
|
|
"^sms ([0-9]{1,2}).([0-9]{1,2}). ([0-9]{2}):([0-9]{2}):([0-9]{2}) ([+*]*[0-9]+[+*/]*[0-9]*) (.*?) \-?([0-9]+,[0-9]{2})([0-9 ]+,[0-9]{2})?$",
|
|
9,
|
|
"Celkem za Roaming - SMS ([0-9 ]+,[0-9]{2})"
|
|
),
|
|
"vpn" => array
|
|
(
|
|
"vpn_calls", "Skupinová volání",
|
|
"voice Datum Èas Volané èíslo Trvání Popis Sleva Volné minuty Kè bez DPH",
|
|
// den, měsíc, hodina, minuta, sekunda, číslo, trvání, skupina, sleva, ?cena?
|
|
"^([0-9]{1,2}).([0-9]{1,2}). ([0-9]{2}):([0-9]{2}):([0-9]{2}) ([+*]*[0-9]+[+*/]*[0-9]*) ([0-9]{2}:[0-9]{2}:[0-9]{2}) (.*?) \-?([0-9]+,[0-9]{2})([0-9 ]+,[0-9]{2})?$",
|
|
10,
|
|
"Celkem za VPN Firma [0-9]{2}:[0-9]{2}:[0-9]{2} ([0-9 ]+,[0-9]{2})"
|
|
),
|
|
"internet" => array
|
|
(
|
|
"internet", "Pøipojení",
|
|
"connect Datum Èas Objem dat v kB Popis Sleva Kè bez DPH",
|
|
// den, měsíc, hodina, minuta, sekunda, objem, apn, cena
|
|
array
|
|
(
|
|
"^connect ([0-9]{1,2}).([0-9]{1,2}). ([0-9]{2}):([0-9]{2}):([0-9]{2}) ([0-9]+) (.*?) \-?([0-9]+,[0-9]{2})$",
|
|
"^connect ([0-9]{1,2}).([0-9]{1,2}). ([0-9]{2}):([0-9]{2}):([0-9]{2}) (.*?) \-?([0-9]+,[0-9]{2})$",
|
|
), 8,
|
|
"Celkem za Pøipojení [0-9]+ ([0-9 ]+,[0-9]{2})"
|
|
),
|
|
"roaming_internet" => array
|
|
(
|
|
"internet", "Pøipojení ze zahranièí",
|
|
"connect Datum Èas Objem dat v kB Popis Sleva Kè bez DPH",
|
|
// den, měsíc, hodina, minuta, sekunda, objem, apn, cena
|
|
"^connect ([0-9]{1,2}).([0-9]{1,2}). ([0-9]{2}):([0-9]{2}):([0-9]{2}) ([0-9]+) (.*?) \-?([0-9]+,[0-9]{2})$",
|
|
8,
|
|
"Celkem za Pøipojení [0-9]+ ([0-9 ]+,[0-9]{2})"
|
|
),
|
|
"pays" => array
|
|
(
|
|
"pays", "Platby tøetím stranám",
|
|
"Datum Èas Volané èíslo Trvání Popis Sleva Kè",
|
|
// den, měsíc, hodina, minuta, sekunda, číslo, popis, sleva, ?cena?
|
|
"^([0-9]{1,2}).([0-9]{1,2}). ([0-9]{2}):([0-9]{2}):([0-9]{2}) (\+?[0-9]+) (.*?) ([0-9]+,[0-9]{2})([0-9 ]+,[0-9]{2})?$",
|
|
9,
|
|
"Celkem za Platby tøetím stranám ([0-9 ]+,[0-9]{2})"
|
|
)
|
|
);
|
|
|
|
/**
|
|
* Seznam nepřipustnych vet, ktere jsou vyhozeny pri predzpracovani.
|
|
*
|
|
* @var array
|
|
*/
|
|
protected static $BANNED_LINES = array
|
|
(
|
|
"3rd", "party", "group", "calls", "roaming", "voice", "roaming", "voice"
|
|
);
|
|
|
|
/**
|
|
* Převod volaného období
|
|
* @param string $period Perioda
|
|
* @return integer Perioda v číselné reprezentaci
|
|
* @throws InvalidArgumentException Při neznámém období
|
|
*/
|
|
protected static function parse_period($period)
|
|
{
|
|
switch ($period)
|
|
{
|
|
case "p":
|
|
return period::PEAK_HOURS;
|
|
break;
|
|
case "Mp":
|
|
return period::OUT_PEAK_HOURS;
|
|
break;
|
|
case "Vkn":
|
|
return period::WEEKEND;
|
|
break;
|
|
case "+=":
|
|
return period::MORE_PERIOD;
|
|
break;
|
|
default:
|
|
throw new InvalidArgumentException(__("Wrong period"));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @param string $emess
|
|
* @param integer $line
|
|
* @return string Chybová zpráva
|
|
*/
|
|
protected static function em($emess, $line = -1)
|
|
{
|
|
return __("Error - cant parse invoice") . ".\n" . $emess
|
|
. (($line > 0) ? "\n" . __("On line") . " " . $line : "");
|
|
}
|
|
|
|
/**
|
|
* Převede číslo z tvaru 7 852 451,60 na float => 7852451.60
|
|
* @param string $price
|
|
* @return float
|
|
*/
|
|
protected static function parse_price($price)
|
|
{
|
|
return floatval(str_replace(array(' ', ','), array('', '.'), $price));
|
|
}
|
|
|
|
/**
|
|
* Převede telefoní číslo s mezerami do tvaru po sobě jdoucích číslic.
|
|
* Pokud číslo neobsahuje předčíslý, doplní jej dle nastavení systému,
|
|
* pokud se jedná o 9-ti místné číslo.
|
|
* Předčíslí je ve tvaru: xxx
|
|
*
|
|
* @param string $number Číslo ve tvaru [(+|00)xxx ]xxx xxx xxx
|
|
* @staticvar string $default_prefix
|
|
* @return string Telefoní číslo
|
|
* @throws InvalidArgumentException Při chybném čísle
|
|
*/
|
|
protected static function parse_phone_number($number)
|
|
{
|
|
static $default_prefix = NULL;
|
|
|
|
if ($default_prefix == NULL)
|
|
{
|
|
$default_country = new Country_Model(Settings::get("default_country"));
|
|
|
|
if (!$default_country->id)
|
|
{
|
|
throw new ErrorException("Invalid default country, check table config and countries!!");
|
|
}
|
|
|
|
$default_prefix = $default_country->country_code;
|
|
}
|
|
|
|
// osekání mezer
|
|
$number = str_replace(" ", "", $number);
|
|
// * nejake specialni cislo
|
|
if (strrchr($number, '*'))
|
|
{
|
|
return $number;
|
|
}
|
|
// kontrola formátu
|
|
if (!mb_ereg("^(\+)?([0-9])+$", $number))
|
|
{
|
|
throw new InvalidArgumentException(__("Wrong phone number"));
|
|
}
|
|
// předčíslí
|
|
if ($number[0] != '+')
|
|
{
|
|
// předvolbu 00 na začátku čísla zahodíme
|
|
if (strncmp($number, "00", 2) == 0)
|
|
{
|
|
$number = substr($number, 2);
|
|
}
|
|
// pokud je číslo nemá předčíslí a je devítimístné vložím předčíslí z configu
|
|
else if (mb_strlen($number) == 9)
|
|
{
|
|
$number = $default_prefix . $number;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
$number = substr($number, 1);
|
|
}
|
|
|
|
return $number;
|
|
}
|
|
|
|
/**
|
|
* Parsovací funkce.
|
|
* Funkce parsuje text z Adobe Readeru (pzn.: testováno na v 9).
|
|
*
|
|
* Obsahuje vnitřní testování správnosti parsování a integrity dat ve 2 bodech:
|
|
* - Testuje zda-li odpovídá počet fakturovaných a parsovaných čísel.
|
|
* - Testuje zda-li odpovídají ceny položek služeb s celkovou cenou za danou službu
|
|
* daného čísla.
|
|
*
|
|
* @param string $text Text k parsování(vstup)
|
|
* @param boolean $integrity_test_enabled Povolení testování integrity čísel
|
|
* v podrobných výpisech
|
|
* @return Bill_Data Data faktury
|
|
* @throws Exception Při chybě při parsování
|
|
* @throws InvalidArgumentException Při prázdném vstupu
|
|
*/
|
|
public static function parse($text, $integrity_test_enabled = TRUE)
|
|
{
|
|
if (empty($text))
|
|
{
|
|
throw new InvalidArgumentException(self::em(__("Empty input")));
|
|
}
|
|
|
|
$tl = mb_split("\n", $text); // vstup rozdělený na pole po řádcích
|
|
|
|
//
|
|
// 0. PREPROCESOR
|
|
//
|
|
|
|
// vyhodit nechtene vety
|
|
foreach ($tl as $k => $v)
|
|
{
|
|
foreach (self::$BANNED_LINES as $ban)
|
|
{
|
|
if (rtrim($v) == $ban)
|
|
unset($tl[$k]);
|
|
}
|
|
}
|
|
// znovu ziskat pole se spravnymi indexi
|
|
$tl = array_values($tl);
|
|
|
|
// potrebe promenne
|
|
|
|
$tlc = count($tl); // počet položek pole
|
|
$tli = 0; // iterátor (aktuální index pole)
|
|
|
|
$data = new Bill_Data(); // datový model
|
|
$number_count = 0; // počet čísel na faktuře (pro testování výsledků parsování)
|
|
|
|
//
|
|
// 1. INFO o FAKTUŘE
|
|
//
|
|
while ($tli < $tlc && $line = rtrim($tl[$tli++]))
|
|
{ // dokud nenaleznu info o faktuře
|
|
// konec textu?
|
|
if (strcmp(mb_strtolower($line),
|
|
mb_strtolower(self::BILL_INFO_STARTER)) == 0)
|
|
{
|
|
if ($tli == $tlc)
|
|
{
|
|
throw new Exception(self::em(
|
|
__("Cannot load heading of invoice") . " " .
|
|
__("End of input"),
|
|
$tli
|
|
));
|
|
}
|
|
// další řádek obsahuje první data
|
|
$line = rtrim($tl[$tli]);
|
|
// kontrola formátu dat
|
|
if (mb_eregi(self::BILL_INFO_REGEX, $line, $r))
|
|
{ // načtení prvních dat
|
|
$data->variable_symbol = $r[3];
|
|
$data->specific_symbol = $r[4];
|
|
$data->date_of_issuance->setDate($r[7], $r[6], $r[5]);
|
|
}
|
|
else
|
|
{ // chybný formát dat
|
|
throw new Exception(self::em(
|
|
__("Cannot load heading of invoice") . " " .
|
|
__("Wrong date format"),
|
|
$tli
|
|
));
|
|
}
|
|
// pokračujeme v načítání ceny faktury
|
|
if (($tli += 2) >= $tlc)
|
|
{ // posun o 2 řádky
|
|
throw new Exception(self::em(
|
|
__("Cannot load heading of invoice") . " " .
|
|
__("End of input"),
|
|
$tli
|
|
));
|
|
}
|
|
$line = rtrim($tl[$tli]);
|
|
// načtení ceny bez DPH
|
|
if (mb_eregi(self::BILL_INFO_PRICE_REGEX, $line, $r))
|
|
{
|
|
$data->dph_rate = $r[1];
|
|
$data->total_price = self::parse_price($r[2]);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception(self::em(
|
|
__("Cannot load heading of invoice") . " " .
|
|
__("Wrong date format"),
|
|
$tli
|
|
));
|
|
}
|
|
// pokračujeme v načítání DPH
|
|
if (++$tli == $tlc)
|
|
{ // posun o řádek
|
|
throw new Exception(self::em(
|
|
__("Cannot load heading of invoice") .
|
|
__("End of input"),
|
|
$tli
|
|
));
|
|
}
|
|
$line = rtrim($tl[$tli]);
|
|
//načtení DPH
|
|
if (mb_eregi(self::BILL_INFO_DPH_REGEX, $line, $r))
|
|
{
|
|
$data->dph = self::parse_price($r[2]);
|
|
}
|
|
else
|
|
{
|
|
throw new Exception(self::em(self::BILL_INFO_ERROR_PARSE, $tli));
|
|
}
|
|
// vyhledání zůčtovacího období
|
|
while ($tli < $tlc && $line = rtrim($tl[$tli++]))
|
|
{
|
|
if (mb_eregi(mb_strtolower(self::BILL_INFO_PERIOD_REGEX),
|
|
mb_strtolower($line), $r))
|
|
{
|
|
$data->billing_period_from->setDate($r[3], $r[2], $r[1]);
|
|
$data->billing_period_to->setDate($r[6], $r[5], $r[4]);
|
|
break; // konec hledání období
|
|
}
|
|
}
|
|
|
|
// @todo: Zde by se mohli načítat další informace pro testování
|
|
// pokračujeme ve vyhledání počtu fakturovaných čísel
|
|
while ($tli < $tlc && $line = rtrim($tl[$tli++]))
|
|
{
|
|
if (mb_eregi(self::BILL_INFO_NUMBERS_COUNT_REGEX, $line, $r))
|
|
{
|
|
$number_count = intval($r[1]);
|
|
break; // konec hledání počtu čísel
|
|
}
|
|
}
|
|
// konec čtení hlavičky
|
|
break;
|
|
}
|
|
}
|
|
// kontrola, zda-li je hlavička načtena
|
|
if ($number_count <= 0)
|
|
{
|
|
throw new Exception(self::em(
|
|
__("Cannot load heading of invoice") .
|
|
__("End of input"),
|
|
$tli
|
|
));
|
|
}
|
|
|
|
// Data internetu pro dlouhé připojení se nezobrazuje v podrobném výpisu,
|
|
// proto je potřeba jej načítat z prvních výpisů
|
|
$pre_number = null;
|
|
while ($tli < $tlc && $line = rtrim($tl[$tli++]))
|
|
{
|
|
try {
|
|
// vyhledání čísla
|
|
if (mb_eregi(self::BILL_EXTRACT_PHONE_REGEX, $line, $r))
|
|
{
|
|
$pre_number = self::parse_phone_number($r[1]);
|
|
continue;
|
|
}
|
|
// vyhledání řádku s dlouhodobým připojením
|
|
else if (mb_eregi(self::BILL_EXTRACT_DATA_LONG_CONNECTIONS, $line, $r) &&
|
|
$pre_number != null)
|
|
{
|
|
$internet = new Internet_Service();
|
|
$internet->date_time->setDate($r[4], $r[3], $r[2]);
|
|
$internet->date_time->setTime($r[5], $r[6], "00");
|
|
$internet->apn = rtrim($r[1]);
|
|
$internet->period = period::NO_PERIOD;
|
|
$internet->transfered = 0;
|
|
$internet->price = self::parse_price($r[7]);
|
|
|
|
try
|
|
{
|
|
$data->add_bill_number($pre_number, new Services($pre_number));
|
|
}
|
|
catch (InvalidArgumentException $ignore)
|
|
{ // číslo již existuje
|
|
}
|
|
|
|
$data->get_bill_number($pre_number)->add_internet($internet);
|
|
}
|
|
// vyhledání řádku s krátkodobým připojením
|
|
else if (mb_eregi(self::BILL_EXTRACT_DATA_DAY_CONNECTIONS, $line, $r) &&
|
|
$pre_number != null)
|
|
{
|
|
$internet = new Internet_Service();
|
|
// neznám datum služby, použiju začátek intervalu
|
|
$internet->date_time = $data->billing_period_from;
|
|
$internet->date_time->setTime("00", "00", "00");
|
|
$internet->apn = rtrim($r[1]);
|
|
$internet->period = period::NO_PERIOD;
|
|
$internet->transfered = 0;
|
|
$internet->price = self::parse_price($r[3]);
|
|
|
|
try
|
|
{
|
|
$data->add_bill_number($pre_number, new Services($pre_number));
|
|
}
|
|
catch (InvalidArgumentException $ignore)
|
|
{ // číslo již existuje
|
|
}
|
|
|
|
$data->get_bill_number($pre_number)->add_internet($internet);
|
|
}
|
|
//
|
|
// 2. NALEZENÍ podrobných výpisů
|
|
//
|
|
// nalezení 2 po sobě jdoucích vět
|
|
else if (strcmp(strtolower(self::BILL_EXTRACT_START_FL),
|
|
strtolower($line)) == 0)
|
|
{
|
|
if ($tli == $tlc)
|
|
{
|
|
throw new Exception(self::em(
|
|
__("Cannot find detail dumps")
|
|
));
|
|
}
|
|
$line = rtrim($tl[$tli++]);
|
|
|
|
// not working after 2011-09
|
|
foreach (self::$BILL_EXTRACT_START_SL as $line_search)
|
|
{
|
|
if (mb_strtolower($line) == mb_strtolower($line_search))
|
|
{
|
|
// nalezeny podrobné výpisy
|
|
break 2;
|
|
}
|
|
}
|
|
reset(self::$BILL_EXTRACT_START_SL);
|
|
|
|
/* repair for invoices release after 2011-09 */
|
|
|
|
if (mb_eregi(self::BILL_EXTRACT_PHONE_REGEX, rtrim($tl[$tli])))
|
|
{
|
|
// nalezeny podrobné výpisy
|
|
break;
|
|
}
|
|
|
|
/* repair END*/
|
|
}
|
|
}
|
|
catch (InvalidArgumentException $e)
|
|
{
|
|
throw new Exception(self::em(
|
|
__("Error - during searching long term connections"), $line
|
|
));
|
|
}
|
|
}
|
|
|
|
// kontrola nalezení výpisů
|
|
if ($tli == $tlc)
|
|
{
|
|
throw new Exception(self::em(__("Cannot find detail dumps")));
|
|
}
|
|
|
|
//
|
|
// 3. DETAILY ČÍSEL
|
|
//
|
|
|
|
$services = NULL;
|
|
// testovací pole cen služeb, čísla indikují
|
|
// ==0 - Netestovat
|
|
// <0 - Testovat
|
|
// >0 - Číslo bylo testováno, hodnota je celková cena služeb
|
|
$test = array
|
|
(
|
|
"call" => 0, "roaming_call" => 0, "sms" => 0, "mms" => 0, "vpn" => 0,
|
|
"internet" => 0, "pays" => 0, "roaming_sms" >= 0
|
|
);
|
|
// procházení čísel
|
|
while ($tli < $tlc && $line = rtrim($tl[$tli++]))
|
|
{
|
|
if (mb_eregi(self::BILL_EXTRACT_PHONE_REGEX, $line, $r))
|
|
{
|
|
try
|
|
{ // zpracování čísla
|
|
$old_number = isset($number) ? $number : NULL;
|
|
$number = self::parse_phone_number($r[1]);
|
|
|
|
// nové číslo?
|
|
if ($old_number != $number)
|
|
{
|
|
// přidání čísla
|
|
if ($old_number != NULL)
|
|
{
|
|
// test služeb čísla na kompletnost
|
|
foreach ($test as $i => $v)
|
|
{
|
|
if ($v < 0)
|
|
{
|
|
throw new Exception(
|
|
url_lang::lang(
|
|
"texts.Near number %s wasnt found data for testing in group %s",
|
|
array($old_number, $i)
|
|
)
|
|
);
|
|
}
|
|
// reset testu
|
|
$test[$i] = 0;
|
|
}
|
|
// přidání čísla
|
|
try
|
|
{
|
|
$data->add_bill_number($old_number, $services);
|
|
}
|
|
catch (InvalidArgumentException $i)
|
|
{
|
|
// číslo již bylo přidáno, přidám již přidané
|
|
// internetové připojení do služeb
|
|
foreach ($data->get_bill_number($old_number)->internet as $net)
|
|
{
|
|
$services->add_internet($net);
|
|
}
|
|
// změním služby
|
|
$data->set_bill_number($old_number, $services);
|
|
}
|
|
}
|
|
// vytvořím služby
|
|
$services = new Services($number);
|
|
}
|
|
}
|
|
catch (Exception $e)
|
|
{
|
|
throw new Exception(self::em($e->getMessage(), $tli));
|
|
}
|
|
// vyhledávám služby
|
|
while ($tli < $tlc && $line = rtrim($tl[$tli++]))
|
|
{
|
|
// hledám služby
|
|
foreach (self::$BILL_EXTRACT_SERVICES as $index => $value)
|
|
{
|
|
// hledání služby, ověření úvodního řádku
|
|
if (strcmp(mb_strtolower($value[self::FLINE]),
|
|
mb_strtolower($line)) == 0)
|
|
{
|
|
// konec textu?
|
|
if ($tli == $tlc)
|
|
{
|
|
throw new Exception(self::em(
|
|
__("Cannot load services - data missing"),
|
|
$tli
|
|
));
|
|
}
|
|
|
|
// ověření 2. řádku
|
|
if (strcmp(mb_strtolower($value[self::SLINE]),
|
|
mb_strtolower(rtrim($tl[$tli]))) != 0)
|
|
{
|
|
continue; // 2. řádek nenalezen, pokračuji dál v hledání
|
|
}
|
|
// posun o řádek
|
|
$tli++;
|
|
// práce s daty
|
|
while ($tli < $tlc && $line = rtrim($tl[$tli++]))
|
|
{
|
|
$matches = false;
|
|
$r = null;
|
|
|
|
// kontrola datového řádku
|
|
if (is_array($value[self::REGEX]))
|
|
{
|
|
foreach ($value[self::REGEX] as $reg)
|
|
{
|
|
if (mb_eregi($reg, $line, $r))
|
|
{
|
|
$matches = true;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else if (mb_eregi($value[self::REGEX], $line, $r))
|
|
{
|
|
$matches = true;
|
|
}
|
|
|
|
if ($matches)
|
|
{
|
|
// aktivace testování
|
|
//$test[$index] = -1;
|
|
// extrakce dat
|
|
try
|
|
{
|
|
switch ($index)
|
|
{
|
|
case "call":
|
|
case "roaming_call":
|
|
$call = new Call_Service();
|
|
$call->date_time->setDate(
|
|
$data->billing_period_to->format("Y"),
|
|
$r[2], $r[1]
|
|
);
|
|
$call->date_time->setTime($r[3], $r[4], $r[5]);
|
|
$call->period = period::NO_PERIOD;
|
|
$call->number = self::parse_phone_number($r[6]);
|
|
$call->length = $r[7];
|
|
$call->description = $r[8];
|
|
if ($index == "roaming_call")
|
|
{
|
|
$call->description = 'Roaming - ' . $r[8];
|
|
}
|
|
$price = self::parse_price($r[9]);
|
|
if ($r[self::$BILL_EXTRACT_SERVICES[$index][self::REGEX_COUNT]] !== false)
|
|
{
|
|
$price += self::parse_price($r[10]);
|
|
}
|
|
$call->price = $price;
|
|
$services->add_call($call);
|
|
break;
|
|
case "sms":
|
|
$sms = new Sms_Service();
|
|
$sms->date_time->setDate(
|
|
$data->billing_period_to->format("Y"),
|
|
$r[2], $r[1]
|
|
);
|
|
$sms->date_time->setTime($r[3], $r[4], $r[5]);
|
|
$sms->period = period::NO_PERIOD;
|
|
$sms->number = self::parse_phone_number($r[6]);
|
|
$sms->description = $r[7];
|
|
$price = self::parse_price($r[8]);
|
|
if ($r[self::$BILL_EXTRACT_SERVICES[$index][self::REGEX_COUNT]] !== false)
|
|
{
|
|
$price += self::parse_price($r[9]);
|
|
}
|
|
$sms->price = $price;
|
|
$services->add_sms($sms);
|
|
break;
|
|
case "roaming_sms":
|
|
$sms = new RoamingSms_Service();
|
|
$sms->date_time->setDate(
|
|
$data->billing_period_to->format("Y"),
|
|
$r[2], $r[1]
|
|
);
|
|
$sms->date_time->setTime($r[3], $r[4], $r[5]);
|
|
// in new invoice, roaming are with phone number (OMG!!!)
|
|
$sms->roaming_zone = self::parse_phone_number($r[6]) . ': ' . $r[7];
|
|
$price = self::parse_price($r[8]);
|
|
if ($r[self::$BILL_EXTRACT_SERVICES[$index][self::REGEX_COUNT]] !== false)
|
|
{
|
|
$price += self::parse_price($r[9]);
|
|
}
|
|
$sms->price = $price;
|
|
$services->add_roaming_sms($sms);
|
|
break;
|
|
case "mms":
|
|
$mms = new Sms_Service();
|
|
$mms->date_time->setDate(
|
|
$data->billing_period_to->format("Y"),
|
|
$r[2], $r[1]
|
|
);
|
|
$mms->date_time->setTime($r[3], $r[4], $r[5]);
|
|
$mms->period = period::NO_PERIOD;
|
|
$mms->number = self::parse_phone_number($r[6]);
|
|
$mms->description = "MMS - " . $r[7];
|
|
$price = self::parse_price($r[8]);
|
|
if ($r[self::$BILL_EXTRACT_SERVICES[$index][self::REGEX_COUNT]] !== false)
|
|
{
|
|
$price += self::parse_price($r[9]);
|
|
}
|
|
$mms->price = $price;
|
|
$services->add_sms($mms);
|
|
break;
|
|
case "pays":
|
|
$pay = new Pay_Service();
|
|
$pay->date_time->setDate(
|
|
$data->billing_period_to->format("Y"),
|
|
$r[2], $r[1]
|
|
);
|
|
$pay->date_time->setTime($r[3], $r[4], $r[5]);
|
|
$pay->number = self::parse_phone_number($r[6]);
|
|
$pay->description = $r[7];
|
|
$price = self::parse_price($r[8]);
|
|
if ($r[self::$BILL_EXTRACT_SERVICES[$index][self::REGEX_COUNT]] !== false)
|
|
{
|
|
$price += self::parse_price($r[9]);
|
|
}
|
|
$pay->price = $price;
|
|
$services->add_pay($pay);
|
|
break;
|
|
case "vpn":
|
|
$call = new Vpn_Call_Service();
|
|
$call->date_time->setDate(
|
|
$data->billing_period_to->format("Y"),
|
|
$r[2], $r[1]
|
|
);
|
|
$call->date_time->setTime($r[3], $r[4], $r[5]);
|
|
$call->period = period::NO_PERIOD;
|
|
$call->number = self::parse_phone_number($r[6]);
|
|
$call->length = $r[7];
|
|
$call->group = $r[8];
|
|
$price = self::parse_price($r[9]);
|
|
if ($r[self::$BILL_EXTRACT_SERVICES[$index][self::REGEX_COUNT]] !== false)
|
|
{
|
|
$price += self::parse_price($r[10]);
|
|
}
|
|
$call->price = $price;
|
|
$services->add_vpn_call($call);
|
|
break;
|
|
case "internet":
|
|
case "roaming_internet":
|
|
$net = new Internet_Service();
|
|
// // den, měsíc, hodina, minuta, sekunda, objem, apn, cena
|
|
$net->date_time->setDate(
|
|
$data->billing_period_to->format("Y"),
|
|
$r[2], $r[1]
|
|
);
|
|
$net->date_time->setTime($r[3], $r[4], $r[5]);
|
|
$net->period = period::NO_PERIOD;
|
|
if (count($r) > self::$BILL_EXTRACT_SERVICES[$index][self::REGEX_COUNT])
|
|
{
|
|
$net->transfered = intval($r[6]);
|
|
$net->apn = $r[7];
|
|
$net->price = self::parse_price($r[8]);
|
|
}
|
|
else
|
|
{
|
|
$net->transfered = null;
|
|
$net->apn = $r[6];
|
|
$net->price = self::parse_price($r[7]);
|
|
}
|
|
if ($index == "roaming_internet")
|
|
{
|
|
$net->apn = "Připojení ze zahraničí - " . $net->apn;
|
|
}
|
|
$services->add_internet($net);
|
|
break;
|
|
default:
|
|
// tohle by se nemělo nikdy stát :-)
|
|
throw new Exception("Error statement " . $number . " " . $index);
|
|
}
|
|
}
|
|
catch (InvalidArgumentException $e)
|
|
{
|
|
throw new Exception(self::em(
|
|
__("Error - during extraction of data") .
|
|
$e->getMessage(), $tli
|
|
));
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// test celkového součtu služeb kategorie
|
|
// pokud naleznu patičku, testuji
|
|
if (mb_eregi($value[self::LLINE], $line, $r))
|
|
{
|
|
// načtení z patičky
|
|
$tot_price = self::parse_price($r[1]);
|
|
if (count($r) > 2)
|
|
{
|
|
$tot_price += self::parse_price($r[2]);
|
|
}
|
|
// získání testovacích dat
|
|
$tot_calc_price = 0;
|
|
foreach ($services->$value[self::SERVICE_ARRAY] as $s)
|
|
{
|
|
$tot_calc_price += $s->price;
|
|
}
|
|
// vodafone a ostatni sdili pole => nutny odpočet
|
|
if ($index == "roaming_call" && $test["call"] > 0)
|
|
{
|
|
$tot_calc_price -= $test["call"];
|
|
}
|
|
// mms a sms sdili pole => nutny odpocet
|
|
else if ($index == "mms" &&
|
|
$test["sms"] > 0)
|
|
{
|
|
$tot_calc_price -= $test["sms"];
|
|
}
|
|
// mms a sms sdili pole => nutny odpocet
|
|
else if ($index == "sms" &&
|
|
$test["mms"] > 0)
|
|
{
|
|
$tot_calc_price -= $test["mms"];
|
|
}
|
|
// zaokrouhlední na haléře
|
|
$tot_price = round($tot_price, 2);
|
|
$tot_calc_price = round($tot_calc_price, 2);
|
|
// test správnosti dat
|
|
if ($tot_price != $tot_calc_price)
|
|
{
|
|
throw new Exception(self::em(
|
|
url_lang::lang(
|
|
"texts.Near number %s ".
|
|
"differs from price of".
|
|
" services: %s\nCalculated ".
|
|
"price: %s\nInvoiced price %s",
|
|
array(
|
|
$number, $index,
|
|
$tot_calc_price, $tot_price
|
|
)
|
|
),
|
|
$tli
|
|
));
|
|
}
|
|
// uložím testovaná data
|
|
$test[$index] = $tot_price;
|
|
}
|
|
else
|
|
{
|
|
$tli--; // návrat
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
// pokračuji v hledání služeb
|
|
break;
|
|
}
|
|
}
|
|
reset(self::$BILL_EXTRACT_SERVICES);
|
|
// hledám číslo
|
|
if (mb_eregi(self::BILL_EXTRACT_PHONE_REGEX, $line))
|
|
{
|
|
// vrátím se na předchozí řádek a na začátek cyklu, kde se číslo vyhodnotí
|
|
$tli--;
|
|
continue 2;
|
|
}
|
|
}
|
|
// přidání čísla
|
|
try
|
|
{
|
|
// test služeb čísla na kompletnost
|
|
foreach ($test as $i => $v)
|
|
{
|
|
if ($v < 0)
|
|
{
|
|
throw new Exception(self::em(
|
|
url_lang::lang(
|
|
"texts.Near number %s wasnt found data for testing in group",
|
|
$old_number
|
|
)
|
|
));
|
|
}
|
|
// reset testu
|
|
$test[$i] = 0;
|
|
}
|
|
// přidání čísla (na konci dokumentu)
|
|
$data->add_bill_number($number, $services);
|
|
}
|
|
catch (InvalidArgumentException $e)
|
|
{
|
|
throw new Exception(self::em($e->getMessage()));
|
|
}
|
|
}
|
|
}
|
|
|
|
// kontrola načtení všech čísel
|
|
if ($integrity_test_enabled === TRUE &&
|
|
$number_count != count($data->bill_numbers))
|
|
{
|
|
$missing = $number_count - count($data->bill_numbers);
|
|
|
|
throw new Exception(self::em(
|
|
__("Some phones wasn't founded") . ".\n" .
|
|
$missing . " " .
|
|
__("is missing from") ." " . $number_count . "."
|
|
));
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
|
|
}
|