Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[EasyBankFiles] Create DE Return parser #668

Merged
merged 1 commit into from
Jul 26, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
232 changes: 232 additions & 0 deletions packages/EasyBankFiles/src/Parsers/DirectEntryReturn/Parser.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
<?php

declare(strict_types=1);

namespace EonX\EasyBankFiles\Parsers\DirectEntryReturn;

use EonX\EasyBankFiles\Parsers\AbstractLineByLineParser;
use EonX\EasyBankFiles\Parsers\DirectEntryReturn\Results\Header;
use EonX\EasyBankFiles\Parsers\DirectEntryReturn\Results\Trailer;
use EonX\EasyBankFiles\Parsers\DirectEntryReturn\Results\Transaction;
use EonX\EasyBankFiles\Parsers\Error;

final class Parser extends AbstractLineByLineParser
{
/**
* @var string Code for header line
*/
private const HEADER = '0';

/**
* @var int Minimal header line length (calculated from maximum substr arguments)
*/
private const MIN_HEADER_LINE_LENGTH = 80;

/**
* @var int Minimal trailer line length (calculated from maximum substr arguments)
*/
private const MIN_TRAILER_LINE_LENGTH = 80;

/**
* @var int Minimal transaction line length (calculated from maximum substr arguments)
*/
private const MIN_TRANSACTION_LINE_LENGTH = 120;

/**
* @var string Code for trailer line
*/
private const TRAILER = '7';

/**
* @var string Code for transaction
*/
private const TRANSACTION_1 = '1';

/**
* @var string Code for transaction
*/
private const TRANSACTION_2 = '2';

/**
* @var mixed[] $errors
*/
private $errors = [];

/**
* @var \EonX\EasyBankFiles\Parsers\DirectEntryReturn\Results\Header
*/
private $header;

/**
* @var \EonX\EasyBankFiles\Parsers\DirectEntryReturn\Results\Trailer
*/
private $trailer;

/**
* @var \EonX\EasyBankFiles\Parsers\DirectEntryReturn\Results\Transaction[]
*/
private $transactions = [];

/**
* @return \EonX\EasyBankFiles\Parsers\Error[]
*/
public function getErrors(): array
{
return $this->errors;
}

/**
* Get header record.
*/
public function getHeader(): Header
{
return $this->header;
}

/**
* Get trailer record.
*/
public function getTrailer(): Trailer
{
return $this->trailer;
}

/**
* @return \EonX\EasyBankFiles\Parsers\DirectEntryReturn\Results\Transaction[]
*/
public function getTransactions(): array
{
return $this->transactions;
}

/**
* {@inheritDoc}
*/
protected function processLine(int $lineNumber, string $line): void
{
// code is the first character in line
$code = $line[0] ?? self::EMPTY_LINE_CODE;
$lineLength = \strlen($line);

if ($code === self::HEADER && $lineLength >= self::MIN_HEADER_LINE_LENGTH) {
$this->header = $this->processHeader($line);

return;
}

if ($code === self::TRAILER && $lineLength >= self::MIN_TRAILER_LINE_LENGTH) {
$this->trailer = $this->processTrailer($line);

return;
}

if (
($code === self::TRANSACTION_1 || $code === self::TRANSACTION_2) &&
$lineLength >= self::MIN_TRANSACTION_LINE_LENGTH
) {
$this->transactions[] = $this->processTransaction($line);

return;
}

$this->errors[] = new Error(\compact('line', 'lineNumber'));
}

/**
* Process header block of line.
*/
private function processHeader(string $line): Header
{
/** @var string|false $dateProcessed */
$dateProcessed = \substr($line, 74, 6);
/** @var string|false $description */
$description = \substr($line, 62, 12);
/** @var string|false $userFinancialInstitution */
$userFinancialInstitution = \substr($line, 20, 3);
/** @var string|false $userIdSupplyingFile */
$userIdSupplyingFile = \substr($line, 56, 6);
/** @var string|false $userSupplyingFile */
$userSupplyingFile = \substr($line, 30, 26);
/** @var string|false $reelSequenceNumber */
$reelSequenceNumber = \substr($line, 18, 2);

return new Header([
'dateProcessed' => $dateProcessed === false ? null : $dateProcessed,
'description' => $description === false ? null : \trim($description),
'userFinancialInstitution' => $userFinancialInstitution === false ? null : $userFinancialInstitution,
'userIdSupplyingFile' => $userIdSupplyingFile === false ? null : $userIdSupplyingFile,
'userSupplyingFile' => $userSupplyingFile === false ? null : \trim($userSupplyingFile),
'reelSequenceNumber' => $reelSequenceNumber === false ? null : $reelSequenceNumber,
]);
}

/**
* Process trailer block of line.
*/
private function processTrailer(string $line): Trailer
{
/** @var string|false $bsb */
$bsb = \substr($line, 1, 7);
/** @var string|false $numberPayments */
$numberPayments = \substr($line, 74, 6);
/** @var string|false $totalNetAmount */
$totalNetAmount = \substr($line, 20, 10);
/** @var string|false $totalCreditAmount */
$totalCreditAmount = \substr($line, 30, 10);
/** @var string|false $totalDebitAmount */
$totalDebitAmount = \substr($line, 40, 10);

return new Trailer([
'bsb' => $bsb === false ? null : \str_replace('-', '', $bsb),
'numberPayments' => $numberPayments === false ? null : $this->trimLeftZeros($numberPayments),
'totalNetAmount' => $totalNetAmount === false ? null : $this->trimLeftZeros($totalNetAmount),
'totalCreditAmount' => $totalCreditAmount === false ? null : $this->trimLeftZeros($totalCreditAmount),
'totalDebitAmount' => $totalDebitAmount === false ? null : $this->trimLeftZeros($totalDebitAmount),
]);
}

/**
* Process transaction block of line.
*/
private function processTransaction(string $line): Transaction
{
/** @var string|false $accountName */
$accountName = \substr($line, 30, 32);
/** @var string|false $accountNumber */
$accountNumber = \substr($line, 8, 9);
/** @var string|false $amount */
$amount = \substr($line, 20, 10);
/** @var string|false $bsb */
$bsb = \substr($line, 1, 7);
/** @var string|false $lodgmentReference */
$lodgmentReference = \substr($line, 62, 18);
/** @var string|false $originalDayOfProcessing */
$originalDayOfProcessing = \substr($line, 112, 2);
/** @var string|false $originalUserIdNumber */
$originalUserIdNumber = \substr($line, 114, 6);
/** @var string|false $remitterName */
$remitterName = \substr($line, 96, 16);
/** @var string|false $traceAccountNumber */
$traceAccountNumber = \substr($line, 87, 9);
/** @var string|false $traceBsb */
$traceBsb = \substr($line, 80, 7);
/** @var string|false $txnCode */
$txnCode = \substr($line, 18, 2);

return new Transaction([
'accountName' => $accountName === false ? null : \trim($accountName),
'accountNumber' => $accountNumber === false ? null : $accountNumber,
'amount' => $amount === false ? null : $this->trimLeftZeros($amount),
'bsb' => $bsb === false ? null : \str_replace('-', '', $bsb),
'indicator' => $line[17] ?? '',
'lodgmentReference' => $lodgmentReference === false ? null : \trim($lodgmentReference),
'originalDayOfProcessing' => $originalDayOfProcessing === false ? null : \trim($originalDayOfProcessing),
'originalUserIdNumber' => $originalUserIdNumber === false ? null : \trim($originalUserIdNumber),
'recordType' => $line[0] ?? '',
'remitterName' => $remitterName === false ? null : \trim($remitterName),
'traceAccountNumber' => $traceAccountNumber === false ? null : $traceAccountNumber,
'traceBsb' => $traceBsb === false ? null : \str_replace('-', '', $traceBsb),
'txnCode' => $txnCode === false ? null : $txnCode,
]);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
<?php

declare(strict_types=1);

namespace EonX\EasyBankFiles\Parsers\DirectEntryReturn\Results;

use DateTime;
use DateTimeInterface;
use EonX\EasyBankFiles\Parsers\BaseResult;

/**
* @method string|null getDateProcessed()
* @method string|null getDescription()
* @method string|null getUserFinancialInstitution()
* @method string|null getUserIdSupplyingFile()
* @method string|null getUserSupplyingFile()
* @method string|null getReelSequenceNumber()
*/
final class Header extends BaseResult
{
/**
* @var string Date in string representation pattern
*/
private const DATE_STRING_PATTERN = '%s-%s-%s';

/**
* Return processed date as a DateTime object.
*/
public function getDateProcessedObject(): ?DateTimeInterface
{
$value = $this->data['dateProcessed'];

if (
\is_string($value) === true &&
\strlen($value) === 6 &&
\ctype_digit($value) === true
) {
$stringDate = \sprintf(
self::DATE_STRING_PATTERN,
\substr($value, 4, 2),
\substr($value, 2, 2),
\substr($value, 0, 2)
);

return new DateTime($stringDate);
}

return null;
}

/**
* Return object attributes.
*
* @return string[]
*/
protected function initAttributes(): array
{
return [
'dateProcessed',
'description',
'userFinancialInstitution',
'userIdSupplyingFile',
'userSupplyingFile',
'reelSequenceNumber',
];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<?php

declare(strict_types=1);

namespace EonX\EasyBankFiles\Parsers\DirectEntryReturn\Results;

use EonX\EasyBankFiles\Parsers\BaseResult;

/**
* @method string|null getBsb()
* @method string|null getNumberPayments()
* @method string|null getTotalCreditAmount()
* @method string|null getTotalDebitAmount()
* @method string|null getTotalNetAmount()
*/
final class Trailer extends BaseResult
{
/**
* Return object attributes.
*
* @return string[]
*/
protected function initAttributes(): array
{
return ['bsb', 'numberPayments', 'totalNetAmount', 'totalCreditAmount', 'totalDebitAmount'];
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
<?php

declare(strict_types=1);

namespace EonX\EasyBankFiles\Parsers\DirectEntryReturn\Results;

use EonX\EasyBankFiles\Parsers\BaseResult;

/**
* @method string|null getAccountName()
* @method string|null getAccountNumber()
* @method string|null getAmount()
* @method string|null getBsb()
* @method string getIndicator()
* @method string|null getLodgmentReference()
* @method string getOriginalDayOfProcessing()
* @method string getOriginalUserIdNumber()
* @method string getRecordType()
* @method string|null getRemitterName()
* @method string|null getTraceAccountNumber()
* @method string|null getTraceBsb()
* @method string|null getTxnCode()
*/
final class Transaction extends BaseResult
{
/**
* Return object attributes.
*
* @return string[]
*/
protected function initAttributes(): array
{
return [
'accountName',
'accountNumber',
'amount',
'bsb',
'indicator',
'lodgmentReference',
'originalDayOfProcessing',
'originalUserIdNumber',
'recordType',
'remitterName',
'traceAccountNumber',
'traceBsb',
'txnCode',
];
}
}
Loading