Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #11 from brazanation/nfe-key
add NFe Access Key document
- Loading branch information
Showing
3 changed files
with
208 additions
and
4 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,104 @@ | ||
<?php | ||
|
||
namespace Brazanation\Documents; | ||
|
||
use Brazanation\Documents\Exception\InvalidDocument as InvalidDocumentException; | ||
|
||
final class NFeAccessKey implements DocumentInterface | ||
{ | ||
const LABEL = 'NFeAccessKey'; | ||
|
||
const LENGTH = 44; | ||
|
||
const REGEX = '/([\d]{4})/'; | ||
|
||
const MASK = '$1 '; | ||
|
||
const MODEL = 55; | ||
|
||
/** | ||
* @var string | ||
*/ | ||
private $nfeKey; | ||
|
||
/** | ||
* NFeAccessKey constructor. | ||
* | ||
* @param $nfeKey | ||
*/ | ||
public function __construct($nfeKey) | ||
{ | ||
$this->validate($nfeKey); | ||
$this->nfeKey = $nfeKey; | ||
} | ||
|
||
/** | ||
* @param int $state | ||
* @param \DateTime $generatedAt | ||
* @param Cnpj $cnpj | ||
* @param int $serie | ||
* @param int $invoiceNumber | ||
* @param int $controlNumber | ||
* | ||
* @return NFeAccessKey | ||
*/ | ||
public static function generate($state, \DateTime $generatedAt, Cnpj $cnpj, $serie, $invoiceNumber, $controlNumber) | ||
{ | ||
$yearMonth = $generatedAt->format('ym'); | ||
$serie = str_pad($serie, 3, 0, STR_PAD_LEFT); | ||
$model = self::MODEL; | ||
$invoiceNumber = str_pad($invoiceNumber, 9, 0, STR_PAD_LEFT); | ||
$controlNumber = str_pad($controlNumber, 9, 0, STR_PAD_LEFT); | ||
|
||
$baseNumber = "{$state}{$yearMonth}{$cnpj}{$model}{$serie}{$invoiceNumber}{$controlNumber}"; | ||
|
||
$digit = self::calculateDigits($baseNumber); | ||
|
||
return new self("{$baseNumber}{$digit}"); | ||
} | ||
|
||
public function format() | ||
{ | ||
return trim(preg_replace(static::REGEX, static::MASK, $this->nfeKey)); | ||
} | ||
|
||
public function __toString() | ||
{ | ||
return $this->nfeKey; | ||
} | ||
|
||
private function validate($number) | ||
{ | ||
if (empty($number)) { | ||
throw InvalidDocumentException::notEmpty(static::LABEL); | ||
} | ||
if (!$this->isValid($number)) { | ||
throw InvalidDocumentException::isNotValid(static::LABEL, $number); | ||
} | ||
} | ||
|
||
private function isValid($number) | ||
{ | ||
if (strlen($number) != static::LENGTH) { | ||
return false; | ||
} | ||
|
||
if (preg_match("/^{$number[0]}{" . static::LENGTH . '}$/', $number)) { | ||
return false; | ||
} | ||
|
||
$digits = static::calculateDigits(substr($number, 0, -1)); | ||
|
||
return $digits === substr($number, -1); | ||
} | ||
|
||
private static function calculateDigits($baseNumber) | ||
{ | ||
$calculator = new DigitCalculator($baseNumber); | ||
$calculator->useComplementaryInsteadOfModule(); | ||
$calculator->withModule(DigitCalculator::MODULE_11); | ||
$digit = $calculator->calculate(); | ||
|
||
return "{$digit}"; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,67 @@ | ||
<?php | ||
|
||
namespace Brazanation\Documents\Tests; | ||
|
||
use Brazanation\Documents\Cnpj; | ||
use Brazanation\Documents\NFeAccessKey; | ||
|
||
class NFeAccessKeyTest extends DocumentTestCase | ||
{ | ||
public function createDocument($number) | ||
{ | ||
return new NFeAccessKey($number); | ||
} | ||
|
||
public function provideValidNumbers() | ||
{ | ||
return [ | ||
['52060433009911002506550120000007800267301615'], | ||
['11101284613439000180550010000004881093997017'], | ||
]; | ||
} | ||
|
||
public function provideValidNumbersAndExpectedFormat() | ||
{ | ||
return [ | ||
['52060433009911002506550120000007800267301615', '5206 0433 0099 1100 2506 5501 2000 0007 8002 6730 1615'], | ||
]; | ||
} | ||
|
||
public function provideEmptyData() | ||
{ | ||
return [ | ||
[NFeAccessKey::LABEL, ''], | ||
[NFeAccessKey::LABEL, null], | ||
[NFeAccessKey::LABEL, 0], | ||
]; | ||
} | ||
|
||
public function provideInvalidNumber() | ||
{ | ||
return [ | ||
[NFeAccessKey::LABEL, str_pad('1', 44, 1)], | ||
[NFeAccessKey::LABEL, '31841136830118868211870485416765268625116906'], | ||
[NFeAccessKey::LABEL, '21470801245862435081451225624565260861852679'], | ||
[NFeAccessKey::LABEL, '45644318091447671194616059650873352394885852'], | ||
[NFeAccessKey::LABEL, '17214281716057582143671174314277906696193888'], | ||
[NFeAccessKey::LABEL, '56017280182977836779696364362142515138726654'], | ||
[NFeAccessKey::LABEL, '90157126614010548506235171976891004177042525'], | ||
[NFeAccessKey::LABEL, '78457064241662300187501877048374851128754067'], | ||
[NFeAccessKey::LABEL, '39950148079977322431982386613620895568235903'], | ||
[NFeAccessKey::LABEL, '90820939577654114875253907311677136672761216'], | ||
]; | ||
} | ||
|
||
public function testGenerateAValidNumber() | ||
{ | ||
$nfeKey = NFeAccessKey::generate( | ||
52, | ||
\DateTime::createFromFormat('ym', '0604'), | ||
new Cnpj('33009911002506'), | ||
12, | ||
780, | ||
26730161 | ||
); | ||
$this->assertEquals('52060433009911002506550120000007800267301615', "{$nfeKey}"); | ||
} | ||
} |