BaseIdentification::moduleTenValidation()   A
last analyzed

Complexity

Conditions 5
Paths 12

Size

Total Lines 24
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 5
eloc 12
c 1
b 0
f 0
nc 12
nop 1
dl 0
loc 24
rs 9.5555
1
<?php
2
3
namespace Luilliarcec\LaravelEcuadorIdentification\Support;
4
5
use Exception;
6
use Luilliarcec\LaravelEcuadorIdentification\Contracts\IdentificationContract;
7
use Luilliarcec\LaravelEcuadorIdentification\Support\Identifications\PrivateRuc;
8
use Luilliarcec\LaravelEcuadorIdentification\Support\Identifications\PublicRuc;
9
10
class BaseIdentification implements IdentificationContract
11
{
12
    /**
13
     * Number of provinces of Ecuador
14
     * @var int
15
     */
16
    protected $provinces = 24;
17
18
    /**
19
     * Length of the different types of identification
20
     * @var int
21
     */
22
    protected $lenght = 0;
23
24
    /**
25
     * Billing code for identification types
26
     * @var string|null
27
     */
28
    protected $billingCode = null;
29
30
    /**
31
     * Third digit of the identification number
32
     * @var int
33
     */
34
    protected $thirdDigit;
35
36
    /**
37
     * Lasts digits of the identification number
38
     * @var string
39
     */
40
    protected $lastDigits = '';
41
42
    /**
43
     * Represents the position of the verifying digit in the identification number
44
     * @var int
45
     */
46
    protected $checkDigitPosition;
47
48
    /**
49
     * Represents the check coefficients for the identification number
50
     * @var array
51
     */
52
    protected $coefficients;
53
54
    /**
55
     * Validate length identification, province code, third digit, lasts digits and module validations
56
     *
57
     * @param string $identification_number Identification document
58
     * @return string|null Billing code or null
59
     * @throws Exception
60
     */
61
    public function validate(string $identification_number)
62
    {
63
        $this->lenghtValidation($identification_number);
64
        $this->provinceCodeValidation($identification_number);
65
        $this->thirdDigitValidation($identification_number);
66
        $this->lastsDigitsValidation($identification_number);
67
68
        if ($this instanceof PublicRuc || $this instanceof PrivateRuc) {
69
            $this->moduleElevenValidation($identification_number);
70
        } else {
71
            $this->moduleTenValidation($identification_number);
72
        }
73
74
        return $this->billingCode;
75
    }
76
77
    /**
78
     * Initial validation of the identification, not empty, only digits, not less than the given length.
79
     *
80
     * @param string $identification_number Identification document
81
     * @throws Exception
82
     */
83
    protected function lenghtValidation(string $identification_number): void
84
    {
85
        if (empty($identification_number)) {
86
            throw new Exception('Field must have a value.');
87
        }
88
89
        if (!ctype_digit($identification_number)) {
90
            throw new Exception('Field must be digits.');
91
        }
92
93
        if (strlen($identification_number) != $this->lenght) {
94
            throw new Exception("Field must be {$this->lenght} digits.");
95
        }
96
    }
97
98
    /**
99
     * Validate the province code (first two numbers of CI/RUC)
100
     * The first 2 positions correspond to the province where it was issued,
101
     * so the first two numbers will not be greater than 24 or less than 1
102
     *
103
     * @param string $identification_number Identification document
104
     * @throws Exception
105
     */
106
    protected function provinceCodeValidation(string $identification_number): void
107
    {
108
        $code = $this->getProvinceCodeValue($identification_number);
109
110
        if ($code < 1 || $code > $this->provinces) {
111
            throw new Exception("In your province code must be between 01 and {$this->provinces}.");
112
        }
113
    }
114
115
    /**
116
     * Valid the third digit
117
     *
118
     * @param string $identification_number Identification document
119
     * @throws Exception
120
     */
121
    protected function thirdDigitValidation(string $identification_number): void
122
    {
123
        $third_digit = $this->getThirdDigitValue($identification_number);
124
125
        if ($third_digit != $this->thirdDigit) {
126
            throw new Exception("Field must have the third digit equal to {$this->thirdDigit}.");
127
        }
128
    }
129
130
    /**
131
     * Valid the lasts digits
132
     *
133
     * @param string $identification_number Identification document
134
     * @throws Exception
135
     */
136
    protected function lastsDigitsValidation(string $identification_number): void
137
    {
138
        $lasts_digits = $this->getLastsDigitsValue($identification_number);
139
140
        if ($lasts_digits != $this->lastDigits) {
141
            throw new Exception("Field does not have the last digits equal to {$this->lastDigits}.");
142
        }
143
    }
144
145
    /**
146
     * Module 10 Algorithm to validate if Certificates and RUC of natural person are valid.
147
     *
148
     * @param string $identification_number Identification document
149
     * @throws Exception The verified digit does not match the verification digit.
150
     */
151
    protected function moduleTenValidation(string $identification_number): void
152
    {
153
        $check_digit_value = $this->getCheckDigitValue($identification_number);
154
        $numbers = $this->getNumbersAsArray($identification_number);
155
156
157
        $total = 0;
158
159
        foreach ($numbers as $key => $value) {
160
            $proceeds = ($value * $this->coefficients[$key]);
161
162
            if ($proceeds >= 10) {
163
                $proceeds = array_sum(str_split($proceeds));
164
            }
165
166
            $total += $proceeds;
167
        }
168
169
        $residue = $total % 10;
170
171
        $verified_digit_value = $residue == 0 ? $residue : 10 - $residue;
172
173
        if ($verified_digit_value != $check_digit_value) {
174
            throw new Exception('The identification number is invalid.');
175
        }
176
    }
177
178
    /**
179
     * Module 11 Algorithm to validate if RUC of Public Companies and Private Companies are valid.
180
     *
181
     * @param string $identification_number Identification document
182
     * @throws Exception The verified digit does not match the verification digit.
183
     */
184
    protected function moduleElevenValidation(string $identification_number): void
185
    {
186
        $check_digit_value = $this->getCheckDigitValue($identification_number);
187
        $numbers = $this->getNumbersAsArray($identification_number);
188
189
        $total = 0;
190
191
        foreach ($numbers as $key => $value) {
192
            $proceeds = ($value * $this->coefficients[$key]);
193
            $total += $proceeds;
194
        }
195
196
        $residue = $total % 11;
197
198
        $verified_digit_value = $residue == 0 ? $residue : 11 - $residue;
199
200
        if ($verified_digit_value != $check_digit_value) {
201
            throw new Exception('The identification number is invalid.');
202
        }
203
    }
204
205
    /**
206
     * Gets the province code value
207
     *
208
     * @param string $identification_number Identification document
209
     * @return false|string Value of the province code number
210
     */
211
    protected function getProvinceCodeValue(string $identification_number)
212
    {
213
        return substr($identification_number, 0, 2);
214
    }
215
216
    /**
217
     * Gets the third digit number
218
     *
219
     * @param string $identification_number Identification document
220
     * @return false|string Value of the third digit number
221
     */
222
    protected function getThirdDigitValue(string $identification_number)
223
    {
224
        return substr($identification_number, 2, 1);
225
    }
226
227
    /**
228
     * Gets the lasts digits value
229
     *
230
     * @param string $identification_number Identification document
231
     * @return false|string Value of the lasts digits
232
     */
233
    protected function getLastsDigitsValue(string $identification_number)
234
    {
235
        return substr($identification_number, $this->lenght - strlen($this->lastDigits), strlen($this->lastDigits));
236
    }
237
238
    /**
239
     * Gets the value of the verification number
240
     *
241
     * @param string $identification_number Identification document
242
     * @return false|string Value of the verification number
243
     */
244
    protected function getCheckDigitValue(string $identification_number)
245
    {
246
        return substr($identification_number, $this->checkDigitPosition - 1, 1);
247
    }
248
249
    /**
250
     * Get identification numbers for verification as Array
251
     *
252
     * @param string $identification_number Identification document
253
     * @return array Identification numbers for verification
254
     */
255
    protected function getNumbersAsArray(string $identification_number): array
256
    {
257
        return str_split(substr($identification_number, 0, $this->lenght - (strlen($this->lastDigits) + 1)));
258
    }
259
}
260