Projekt

Obecné

Profil

Stáhnout (8.33 KB) Statistiky
| Větev: | Tag: | Revize:
<?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/
*
*/

require_once 'RB_Exception.php';

/**
* Parser_RB (Raiffeisen Bank) is a parser for getting data from a bank account
* statement in the new (2018) XML format.
*
* @author Jakub Juračka
* @version 1.0
*/
class Parser_RB
{

/**
* TYPE OF XML section which contains incoming payments.
*
* @var string
*/
private static $TYPE_INCOME = 'CRDT';

/**
* TYPE OF XML section which contains outgoing payments.
*
* @var string
*/
private static $TYPE_OUTG = 'DBIT';

/**
* TYPE OF XML section for saving BALANCE from the begining and end of
* statement period.
*
* @var string
*/
private static $TYPE_BAL = 'CLAV';

/**
* Store the simple_xml object with bank statement.
*
* @var simple_xml object
*/
protected $data;

/**
* Parsed header of bank statement.
*
* @var array()
*/
protected $header;

/**
* Contains parsed rows of bank statement with incoming/outgoing statements.
*
* @var string
*/
protected $rows;

/**
* Opening datafile and saving simple_xml object to variable $data
*
* @param string $url - File URL path
*
* @author Jakub Juračka
*/
private function open($url)
{
if ($this->data = simplexml_load_file($url))
{
$this->data = $this->data->BkToCstmrStmt->Stmt;
}
else
{
throw new Exception("Can not open file! Check if $url exists!");
}
}

/**
* Loading header and saving array
* with bank account info to the variable $header.
*
* @author Jakub Juračka
*/
private function loadHeader()
{
$datetime_info = $this->data->FrToDt;

$from = isset($datetime_info->FrDtTm) ? $datetime_info->FrDtTm : NULL;
$to = isset($datetime_info->ToDtTm) ? $datetime_info->ToDtTm : NULL;

if (!self::is_correct($from) || !self::is_correct($to))
{
throw new RB_Exception(__('Statement period (FROM - TO) is not set. Please, check the statement header.'));
}

//Proccessing datetime to sql format
$from = str_replace('T', ' ', $from);
$to = str_replace('T', ' ', $to);
////////////////////////////////////

$acc_info = $this->data->Acct;

foreach ($this->data->Bal as $Balance)
{
$type = $Balance->Tp->CdOrPrtry->Cd;

if ($type == self::$TYPE_BAL && !isset($balance_start_obj))
$balance_start_obj = $Balance;

if ($type == self::$TYPE_BAL && $Balance->Dt->Dt != $balance_start_obj->Dt->Dt)
$balance_end_obj = $Balance;
}

if (!isset($balance_start_obj) || !isset($balance_end_obj))
{
throw new RB_Exception(__('Please, check the file. ') . ' '
. __('Missing data in header - balance on START or END of statement period.'));
}

//GETTING BALANCE INFO
$money_status_start = $balance_start_obj->Amt;
$money_status_end = $balance_end_obj->Amt;

//GETTING INFO ABOUT BANK ACOUNT
$IBAN = isset($acc_info->Id->IBAN) ? $acc_info->Id->IBAN : NULL;
$currency = $acc_info->Ccy;

$bank_code = isset($acc_info->Svcr->FinInstnId->Othr->Id) ?
$acc_info->Svcr->FinInstnId->Othr->Id : NULL;

$BIC = isset($acc_info->Svcr->FinInstnId->BIC) ?
$acc_info->Svcr->FinInstnId->BIC : NULL;

$acc_num = substr($IBAN, -10);

if (!self::is_correct($IBAN) || !self::is_correct($bank_code) ||
!self::is_correct($acc_num))
{
throw new RB_Exception(__('Please, check the file.') . ' '
. __('Possible fault in IBAN, BANK CODE or ACCOUNT NUMBER.'));
}

$this->header = array
(
'from' => $from,
'to' => $to,
'IBAN' => $IBAN,
'currency' => $currency,
'bank_nr' => $bank_code,
'BIC' => $BIC,
'account_nr' => $acc_num,
'bal_start' => $money_status_start,
'bal_end' => $money_status_end,
);
}

/**
* Prasing $data variable to variable $rows
*
* @param string $url - File URL path
*
* @author Jakub Juračka
*/
public function parse($url)
{
//FILE LOADING
$this->open($url);

//Loading header (getting info about account assigned to the statement)
$this->loadHeader();

//Parsing data - if datetime, account number, bank_code or amount is not defined => throw an error
$this->rows = array();

//Couting proccessed rows
$iteration = 1;

//Processing payments
foreach ($this->data->Ntry as $row)
{
//Auxiliary variables $type, $detail
$type = $row->CdtDbtInd;
$detail = $row->NtryDtls->TxDtls;

//Testing if the payment is OUTGING/INCOMING
// and saving to the variable $rows
if ($type == self::$TYPE_OUTG)
{
if (!self::is_correct($row->ValDt->DtTm))
self::throw_error_row($iteration, 'Date and time');
if (!self::is_correct($detail->RltdPties->CdtrAcct->Id->Othr->Id))
self::throw_error_row($iteration, 'Account number');
if (!self::is_correct($detail->RltdAgts->CdtrAgt->FinInstnId->Othr->Id))
self::throw_error_row($iteration, 'Bank code');
if (!self::is_correct($row->Amt))
self::throw_error_row($iteration, 'Amount');

array_push($this->rows, array
(
'datetime' => $row->ValDt->DtTm,
'transaction_id' => isset($row->NtryRef) ? intval($row->NtryRef) : NULL,
'acc_num' => strval($detail->RltdPties->CdtrAcct->Id->Othr->Id),
'vs' => isset($detail->Refs->EndToEndId) ?
intval($detail->Refs->EndToEndId) : NULL,
'ks' => isset($detail->Refs->InstrId) ?
intval($detail->Refs->InstrId) : NULL,
'ss' => isset($detail->Refs->PmtInfId) ?
intval($detail->Refs->PmtInfId) : NULL,
'name' => isset($detail->RltdPties->DbtrAcct->Nm) ?
strval($detail->RltdPties->DbtrAcct->Nm) : NULL,
'bank_code' => strval($detail->RltdAgts->CdtrAgt->FinInstnId->Othr->Id),
'amount' => ($row->Amt) * (-1),
'text' => isset($detail->AddtlTxInf) ? strval($detail->AddtlTxInf) : ''
));
}
else if ($type == self::$TYPE_INCOME)
{
if (!self::is_correct($row->ValDt->DtTm))
self::throw_error_row($iteration, 'Date and time');
if (!self::is_correct($detail->RltdPties->DbtrAcct->Id->Othr->Id))
self::throw_error_row($iteration, 'Account number');
if (!self::is_correct($detail->RltdAgts->DbtrAgt->FinInstnId->Othr->Id))
self::throw_error_row($iteration, 'Bank code');
if (!self::is_correct($row->Amt))
self::throw_error_row($iteration, 'Amount');

array_push($this->rows, array
(
'datetime' => $row->ValDt->DtTm,
'transaction_id' => isset($row->NtryRef) ? intval($row->NtryRef) : NULL,
'acc_num' => strval($detail->RltdPties->DbtrAcct->Id->Othr->Id),
'vs' => isset($detail->Refs->EndToEndId) ?
intval($detail->Refs->EndToEndId) : NULL,
'ks' => isset($detail->Refs->InstrId) ?
intval($detail->Refs->InstrId) : NULL,
'ss' => isset($detail->Refs->PmtInfId) ?
intval($detail->Refs->PmtInfId) : NULL,
'name' => isset($detail->RltdPties->DbtrAcct->Nm) ?
strval($detail->RltdPties->DbtrAcct->Nm) : NULL,
'bank_code' => strval($detail->RltdAgts->DbtrAgt->FinInstnId->Othr->Id),
'amount' => $row->Amt,
'text' => isset($detail->AddtlTxInf) ? strval($detail->AddtlTxInf) : ''
));
}

$iteration++;
}
}

/**
* Function which only returns rows with incoming/outgoing payments
*
* @author Jakub Juračka
*/
public function get_data()
{
return $this->rows;
}

/**
* Function which only returns info about account assigned with bank
* statement.
*
* @author Jakub Juračka
*/
public function get_header()
{
return $this->header;
}

/**
* Function for checking data correctness
*
* @param string $data
*
* @author Jakub Juračka
*/
private function is_correct($data)
{
return isset($data) && $data != NULL && $data != '';
}

/**
* Shortcut for error throwing
*
* @param int $row_num
* @param string $datatype
*
* @author Jakub Juračka
*/
private function throw_error_row($row_num, $datatype)
{
throw new RB_Exception(__('Please, check the file.') . ' '
. __('Missing data (%s) on the line %d.', array($datatype, $row_num)));
}

}
(1-1/3)