Skip to content

Commit

Permalink
Fix: lv_LV generating invalid personal identity numbers (#663)
Browse files Browse the repository at this point in the history
  • Loading branch information
edgarsn committed Jul 9, 2023
1 parent 35bddf2 commit 05bc4de
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 4 deletions.
28 changes: 24 additions & 4 deletions src/Faker/Provider/lv_LV/Person.php
Expand Up @@ -2,7 +2,6 @@

namespace Faker\Provider\lv_LV;

use Faker\Calculator\Luhn;
use Faker\Provider\DateTime;

class Person extends \Faker\Provider\Person
Expand Down Expand Up @@ -145,11 +144,32 @@ public function personalIdentityNumber(\DateTime $birthdate = null)
$birthdate = DateTime::dateTimeThisCentury();
}

$year = $birthdate->format('Y');

if ($year >= 2000 && $year <= 2099) {
$century = 2;
} elseif ($year >= 1900 && $year <= 1999) {
$century = 1;
} else {
$century = 0;
}

$datePart = $birthdate->format('dmy');
$randomDigits = (string) static::numerify('####');
$serialNumber = static::numerify('###');

$partialNumberSplit = str_split($datePart . $century . $serialNumber);

$idDigitValidator = [1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
$total = 0;

foreach ($partialNumberSplit as $key => $digit) {
if (isset($idDigitValidator[$key])) {
$total += $idDigitValidator[$key] * (int) $digit;
}
}

$checksum = Luhn::computeCheckDigit($datePart . $randomDigits);
$checksumDigit = (1101 - $total) % 11 % 10;

return $datePart . '-' . $randomDigits . $checksum;
return $datePart . '-' . $century . $serialNumber . $checksumDigit;
}
}
37 changes: 37 additions & 0 deletions test/Faker/Provider/lv_LV/PersonTest.php
@@ -0,0 +1,37 @@
<?php

namespace Faker\Test\Provider\lv_LV;

use Faker\Provider\lv_LV\Person;
use Faker\Test\TestCase;

/**
* @group legacy
*/
final class PersonTest extends TestCase
{
public function testPersonalIdentityNumber(): void
{
$idNumber = $this->faker->personalIdentityNumber();

self::assertMatchesRegularExpression('/^[0-9]{6}-[0-9]{5}$/', $idNumber);
}

public function testChecksumDigitCalculation(): void
{
$idNumber = $this->faker->personalIdentityNumber(\DateTime::createFromFormat('Y-m-d', '1981-05-24'));

$serialNumber = substr($idNumber, 8, 3);
$serialNumberSplit = str_split($serialNumber);

// calculate checksum, using static digits from date (2 4 0 5 8 1 1) and inserting random serial number digits
$checksumDigit = (1101 - (1 * 2 + 6 * 4 + 3 * 0 + 7 * 5 + 9 * 8 + 10 * 1 + 5 * 1 + 8 * (int) $serialNumberSplit[0] + 4 * (int) $serialNumberSplit[1] + 2 * (int) $serialNumberSplit[2])) % 11 % 10;

self::assertSame('240581-1' . $serialNumber . $checksumDigit, $idNumber);
}

protected function getProviders(): iterable
{
yield new Person($this->faker);
}
}

0 comments on commit 05bc4de

Please sign in to comment.