Completed
Pull Request — master (#24)
by Antonio Oertel
02:30
created

AbstractAccessKey::loadFromKey()   B

Complexity

Conditions 1
Paths 1

Size

Total Lines 26
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 18
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 26
ccs 18
cts 18
cp 1
rs 8.8571
c 0
b 0
f 0
cc 1
eloc 17
nc 1
nop 1
crap 1
1
<?php
2
3
namespace Brazanation\Documents\Sped;
4
5
use Brazanation\Documents\AbstractDocument;
6
use Brazanation\Documents\Cnpj;
7
use Brazanation\Documents\DigitCalculator;
8
9
/**
10
 * Class SpedAccessKey
11
 *
12
 * @package Brazanation\Documents
13
 *
14
 * @property int       $state
15
 * @property \DateTime $generatedAt
16
 * @property Cnpj      $cnpj
17
 * @property int       $model
18
 * @property int       $sequence
19
 * @property int       $invoiceNumber
20
 * @property int       $controlNumber
21
 */
22
abstract class AbstractAccessKey extends AbstractDocument
23
{
24
    const LABEL = 'SpedAccessKey';
25
26
    const LENGTH = 44;
27
28
    const REGEX = '/([\d]{4})/';
29
30
    const MASK = '$1 ';
31
32
    protected $state;
33
34
    protected $generatedAt;
35
36
    protected $cnpj;
37
38
    protected $model;
39
40
    protected $sequence;
41
42
    protected $invoiceNumber;
43
44
    protected $controlNumber;
45
46
    /**
47
     * SpedAccessKey constructor.
48
     *
49
     * @param $accessKey
50
     */
51 81
    public function __construct($accessKey)
52
    {
53 81
        $accessKey = preg_replace('/\D/', '', $accessKey);
54 81
        parent::__construct($accessKey, static::LENGTH, 1, static::LABEL);
55 16
        $this->loadFromKey($accessKey);
56 16
    }
57
58 16
    private function loadFromKey($accessKey)
59
    {
60 16
        $startPosition = 0;
61 16
        $this->state = substr($accessKey, $startPosition, 2);
62
63 16
        $startPosition += 2;
64 16
        $this->generatedAt = \DateTime::createFromFormat('ymd H:i:s', substr($accessKey, $startPosition, 4) . '01 00:00:00');
65
66 16
        $startPosition += 4;
67 16
        $this->cnpj = new Cnpj(substr($accessKey, $startPosition, 14));
68
69 16
        $startPosition += 14;
70 16
        $this->model = new Model(substr($accessKey, $startPosition, 2));
71
72 16
        $startPosition += 2;
73 16
        $this->sequence = substr($accessKey, $startPosition, 3);
74
75 16
        $startPosition += 3;
76 16
        $this->invoiceNumber = substr($accessKey, $startPosition, 9);
77
78 16
        $startPosition += 9;
79 16
        $this->controlNumber = substr($accessKey, $startPosition, 9);
80
81 16
        $startPosition += 9;
82 16
        $this->digit = substr($accessKey, $startPosition, 1);
83 16
    }
84
85
    /**
86
     * Generates a valid Sped Access Key.
87
     *
88
     * @param int       $state         IBGE state code.
89
     * @param \DateTime $generatedAt   Year and month when invoice was created.
90
     * @param Cnpj      $cnpj          Cnpj from issuer.
91
     * @param Model     $model         Document model.
92
     * @param int       $sequence      Invoice sequence.
93
     * @param int       $invoiceNumber Invoice number.
94
     * @param int       $controlNumber Control number.
95
     *
96
     * @return AbstractAccessKey
97
     */
98 5
    protected static function generateKey(
99
        $state,
100
        \DateTime $generatedAt,
101
        Cnpj $cnpj,
102
        Model $model,
103
        $sequence,
104
        $invoiceNumber,
105
        $controlNumber
106
    ) {
107 5
        $yearMonth = $generatedAt->format('ym');
108 5
        $sequence = str_pad($sequence, 3, 0, STR_PAD_LEFT);
109 5
        $invoiceNumber = str_pad($invoiceNumber, 9, 0, STR_PAD_LEFT);
110 5
        $controlNumber = str_pad($controlNumber, 9, 0, STR_PAD_LEFT);
111
112 5
        $baseNumber = "{$state}{$yearMonth}{$cnpj}{$model}{$sequence}{$invoiceNumber}{$controlNumber}";
113
114 5
        $digit = self::calculateDigitFrom($baseNumber);
115
116 5
        $instance = new static("{$baseNumber}{$digit}");
117 5
        $instance->generatedAt = $generatedAt;
118
119 5
        return $instance;
120
    }
121
122
    /**
123
     * {@inheritdoc}
124
     */
125 5
    public function format()
126
    {
127 5
        return trim(preg_replace(self::REGEX, self::MASK, "{$this}"));
128
    }
129
130
    /**
131
     * {@inheritdoc}
132
     */
133 61
    public function calculateDigit($baseNumber)
134
    {
135 61
        return self::calculateDigitFrom($baseNumber);
136
    }
137
138
    /**
139
     * Calculate check digit from base number.
140
     *
141
     * It is static because is used from generate static method.
142
     *
143
     * @param string $baseNumber Base numeric section to be calculate your digit.
144
     *
145
     * @return string
146
     */
147 61
    public static function calculateDigitFrom($baseNumber)
148
    {
149 61
        $calculator = new DigitCalculator($baseNumber);
150 61
        $calculator->useComplementaryInsteadOfModule();
151 61
        $calculator->withModule(DigitCalculator::MODULE_11);
152 61
        $digit = $calculator->calculate();
153
154 61
        return "{$digit}";
155
    }
156
}
157