diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index acd0b0a..a7cc2c7 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -27,7 +27,7 @@ jobs:
env:
fail-fast: true
- name: Code style (phpcs)
- run: phpcs -q --report=checkstyle src/ tests/ | cs2pr
+ run: phpcs -q --report=checkstyle | cs2pr
php-cs-fixer:
name: Code style (php-cs-fixer)
diff --git a/.phive/phars.xml b/.phive/phars.xml
index 7aa1b73..2b77702 100644
--- a/.phive/phars.xml
+++ b/.phive/phars.xml
@@ -1,9 +1,9 @@
-
+
-
-
+
+
diff --git a/README.md b/README.md
index 8b68651..bc823be 100644
--- a/README.md
+++ b/README.md
@@ -95,6 +95,21 @@ Provee métodos para crear una cadena de caracteres que es una clave RFC:
- `RfcFaker::mexicanRfcMoral()` para persona moral (12 posiciones).
- `RfcFaker::mexicanRfc()` indistintamente una persona moral o física.
+## Dígito verificador
+
+Se puede obtener el dígito verificador calculado con el método `Rfc::calculateCheckSum()`,
+así como conocer si el dígito verificador coincide con el método `Rfc::doesCheckSumMatch()`.
+
+La además provee la clase `CheckSum` para realizar el cálculo del dígito verificador de un RFC.
+Cabe mencionar que, si bien debería ser siempre coincidente, hay algunos casos donde esto
+no se respeta (SAT, ¿todo bien?), por ejemplo, el caso de *Restaurantes TOKS* ha tenido
+los RFC `RT0840921REA` (dígito `A`) y también `RT0840921RE4`.
+
+Puede ver el procedimiento del dígito verificador en alguno de estos enlaces:
+
+-
+-
+
## Desarrollo
Para entender esta librería en el ámbito de desarrollo (para extender o modificar), lee los siguientes documentos:
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 080aa5d..27491f8 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -8,6 +8,16 @@ Utilizamos [Versionado Semántico 2.0.0](SEMVER.md).
Los cambios no liberados no requieren de una nueva versión y son incluidos en la rama principal.
+## Versión 1.1.2
+
+Se actualiza la clase `CheckSum` y se mejoran las pruebas unitarias sobre la misma.
+Gracias a `@fitorec` por sus sugerencias en el [PR #14](https://github.com/phpcfdi/rfc/pull/14).
+
+Se actualizan las versiones de las herramientas de desarrollo.
+
+Al ejecutar el trabajo de integración continua en el trabajo `phpcs` se usan los directorios según
+el archivo de configuración.
+
## Versión 1.1.1
Se actualiza la expresión regular para lectura de RFC con las recomendaciones de simplificación:
diff --git a/src/CheckSum.php b/src/CheckSum.php
index 5bc4207..de3d1d8 100644
--- a/src/CheckSum.php
+++ b/src/CheckSum.php
@@ -8,23 +8,25 @@ final class CheckSum
{
private const DICTIONARY = [0 => 0, 1 => 1, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6, 7 => 7, 8 => 8, 9 => 9, 'A' => 10, 'B' => 11, 'C' => 12, 'D' => 13, 'E' => 14, 'F' => 15, 'G' => 16, 'H' => 17, 'I' => 18, 'J' => 19, 'K' => 20, 'L' => 21, 'M' => 22, 'N' => 23, '&' => 24, 'O' => 25, 'P' => 26, 'Q' => 27, 'R' => 28, 'S' => 29, 'T' => 30, 'U' => 31, 'V' => 32, 'W' => 33, 'X' => 34, 'Y' => 35, 'Z' => 36, ' ' => 37, '#' => 38];
+ private const DIGIT_OVERRIDE = [10 => 'A', 11 => '0'];
+
public function calculate(string $rfc): string
{
- // 'Ñ' translated to '#' because 'Ñ' is multibyte 0xC3 0xB1
+ // 'Ñ' cambia a '#' porque 'Ñ' es multi-byte 0xC3 0xB1
$chars = str_split(str_replace('Ñ', '#', $rfc), 1);
- array_pop($chars); // remove predefined checksum
$length = count($chars);
- $sum = (11 === $length) ? 481 : 0; // 481 para morales, 0 para físicas
- $j = $length + 1;
+ array_pop($chars); // remover el dígito predefinido
+
+ // Valor inicial de la suma: 481 para morales, 0 para físicas
+ $sum = (12 === $length) ? 481 : 0;
+ // suma de valores: Σ(Vi * (Pi + 1))
foreach ($chars as $i => $char) {
- $sum += self::DICTIONARY[$char] * ($j - $i);
+ $sum += (self::DICTIONARY[$char] ?? 0) * ($length - $i);
}
- $digit = strval(11 - $sum % 11);
- if ('11' === $digit) {
- $digit = '0';
- } elseif ('10' === $digit) {
- $digit = 'A';
- }
- return $digit;
+
+ // posibles valores: [1, 2, ..., 10, 11] porque $sum % 11 => int<0, 10>
+ $digit = 11 - $sum % 11;
+ // se retorna 10 => 0, 11 => A o el valor obtenido
+ return self::DIGIT_OVERRIDE[$digit] ?? strval($digit);
}
}
diff --git a/tests/Unit/CheckSumTest.php b/tests/Unit/CheckSumTest.php
index 75c612f..e9b1308 100644
--- a/tests/Unit/CheckSumTest.php
+++ b/tests/Unit/CheckSumTest.php
@@ -9,20 +9,29 @@
final class CheckSumTest extends TestCase
{
- public function testCheckSum(): void
+ /** @return array */
+ public function providerCheckSum(): array
{
- $expected = 'A';
- $rfc = 'COSC8001137NA';
+ return [
+ 'física 0' => ['CAMA911215CJ0', '0'],
+ 'física A' => ['COSC8001137NA', 'A'],
+ 'física [1-9]' => ['SORC591116FJ6', '6'],
- $checksum = new CheckSum();
- $this->assertSame($expected, $checksum->calculate($rfc));
+ 'moral A' => ['DIM8701081LA', 'A'],
+ 'moral 0' => ['A&A050908GT0', '0'],
+ 'moral [1-9]' => ['SAT970701NN3', '3'],
+
+ 'multibyte' => ['AÑÑ801231JK0', '0'],
+
+ 'empty rfc' => ['', '0'],
+ 'invalid rfc' => ['$', '0'],
+ 'invalid chars' => ['AAA010101$$$', '7'], // $ is managed as 0
+ ];
}
- public function testCheckSumWithMultiByte(): void
+ /** @dataProvider providerCheckSum */
+ public function testCheckSum(string $rfc, string $expected): void
{
- $expected = '0';
- $rfc = 'AÑÑ801231JK0';
-
$checksum = new CheckSum();
$this->assertSame($expected, $checksum->calculate($rfc));
}