Skip to content

Commit 7b97273

Browse files
CaptainPeroxCedricGordon
andauthored
Added support for belgian BIS-number (#118)
Co-authored-by: CedricGordon <cedricgordon@webdoos.be>
1 parent 07515cd commit 7b97273

4 files changed

Lines changed: 96 additions & 9 deletions

File tree

src/Core/Europe/Belgium/BelgiumCitizenInformationExtractor.php

Lines changed: 43 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,18 @@ public function extract(string $id): Citizen
2525
throw new InvalidIdException();
2626
}
2727

28-
$gender = $this->getGender($id);
29-
$dateOfBirth = $this->getDateOfBirth($id);
30-
3128
$citizen = new Citizen();
32-
$citizen->setGender($gender);
33-
$citizen->setDateOfBirth($dateOfBirth);
29+
30+
// BIS numbers: month + 20 = gender unknown, month + 40 = gender known
31+
// Regular NRN: always has gender
32+
if (!$this->isBisNumber($id) || $this->isBisGenderKnown($id)) {
33+
$citizen->setGender($this->getGender($id));
34+
}
35+
36+
// Extract DOB if birthdate is known (month is not 00, 20, or 40)
37+
if (!$this->isBirthdateUnknown($id)) {
38+
$citizen->setDateOfBirth($this->getDateOfBirth($id));
39+
}
3440

3541
return $citizen;
3642
}
@@ -40,7 +46,31 @@ private function sanitize(string $id): string
4046
return str_replace(['-', ' ', '.'], '', $id);
4147
}
4248

43-
private function getGender(int $id): Gender
49+
private function isBisNumber(string $id): bool
50+
{
51+
$month = (int) substr($id, 2, 2);
52+
53+
return $month > 12;
54+
}
55+
56+
private function isBisGenderKnown(string $id): bool
57+
{
58+
$month = (int) substr($id, 2, 2);
59+
60+
// Month + 40 means gender is known, month + 20 means gender is unknown
61+
return $month >= 40;
62+
}
63+
64+
private function isBirthdateUnknown(string $id): bool
65+
{
66+
$month = (int) substr($id, 2, 2);
67+
68+
// For BIS numbers only: month 20 or 40 means birthdate is unknown
69+
// Regular NRN with month 00 still extracts DOB (defaults to January)
70+
return $month === 20 || $month === 40;
71+
}
72+
73+
private function getGender(string $id): Gender
4474
{
4575
return (substr($id, 6, 3) % 2) ? Gender::Male : Gender::Female;
4676
}
@@ -54,6 +84,13 @@ private function getDateOfBirth(string $id): DateTime
5484
$month = (int) $month;
5585
$day = (int) $day;
5686

87+
// BIS numbers have 20 or 40 added to the month
88+
if ($month >= 40) {
89+
$month -= 40;
90+
} elseif ($month >= 20) {
91+
$month -= 20;
92+
}
93+
5794
// use first day or month if unknown
5895
$month = $month === 0 ? 1 : $month;
5996
$day = $day === 0 ? 1 : $day;

src/Core/Europe/Belgium/BelgiumIdValidator.php

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,13 @@ private function validDateOfBirth(string $id, bool $after2000): bool
8484
$month = (int) $month;
8585
$day = (int) $day;
8686

87+
// BIS numbers have 20 or 40 added to the month
88+
if ($month >= 40) {
89+
$month -= 40;
90+
} elseif ($month >= 20) {
91+
$month -= 20;
92+
}
93+
8794
$month = $month === 0 ? 1 : $month;
8895
$day = $day === 0 ? 1 : $day;
8996

src/Models/Citizen.php

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,21 +13,21 @@ class Citizen
1313
*
1414
* @var Gender|null
1515
*/
16-
private ?Gender $gender;
16+
private ?Gender $gender = null;
1717

1818
/**
1919
* The date of birth as a DateTime object.
2020
*
2121
* @var DateTime|null
2222
*/
23-
private ?DateTime $dateOfBirth;
23+
private ?DateTime $dateOfBirth = null;
2424

2525
/**
2626
* The place of birth as a string.
2727
*
2828
* @var string|null
2929
*/
30-
private ?string $placeOfBirth;
30+
private ?string $placeOfBirth = null;
3131

3232
/**
3333
* Get the citizen's gender.

tests/Feature/Europe/BelgiumTest.php

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
class BelgiumTest extends FeatureTestCase
1212
{
1313
private array $people;
14+
private array $bisNumbers;
1415
private array $invalidIds;
1516

1617
public function setUp(): void
@@ -50,6 +51,29 @@ public function setUp(): void
5051
]
5152
];
5253

54+
$this->bisNumbers = [
55+
'dobAndGenderUnknown1' => [
56+
'id' => '11200274580',
57+
'gender' => null,
58+
'dob' => null,
59+
],
60+
'dobAndGenderUnknown2' => [
61+
'id' => '00200203376',
62+
'gender' => null,
63+
'dob' => null,
64+
],
65+
'dobUnknownGenderKnown' => [
66+
'id' => '00400048320',
67+
'gender' => Gender::Male,
68+
'dob' => null,
69+
],
70+
'dobAndGenderKnown' => [
71+
'id' => '00421090786',
72+
'gender' => Gender::Male,
73+
'dob' => new DateTime('2000-02-10'),
74+
],
75+
];
76+
5377
$this->invalidIds = [
5478
'12.12.12-132.32',
5579
'97.12.03-123.12',
@@ -94,4 +118,23 @@ public function test_validation_behaviour(): void
94118

95119
$this->socrates->getCitizenDataFromId('12.12.12-1323.32', Country::Belgium);
96120
}
121+
122+
public function test_bis_number_validation(): void
123+
{
124+
foreach ($this->bisNumbers as $bisNumber) {
125+
self::assertTrue(
126+
$this->socrates->validateId($bisNumber['id'], Country::Belgium)
127+
);
128+
}
129+
}
130+
131+
public function test_bis_number_extraction(): void
132+
{
133+
foreach ($this->bisNumbers as $bisNumber) {
134+
$citizen = $this->socrates->getCitizenDataFromId($bisNumber['id'], Country::Belgium);
135+
136+
self::assertEquals($bisNumber['gender'], $citizen->getGender());
137+
self::assertEquals($bisNumber['dob'], $citizen->getDateOfBirth());
138+
}
139+
}
97140
}

0 commit comments

Comments
 (0)