Skip to content

Commit

Permalink
update docs, remove unused pkgs, version bump: v1.0.1
Browse files Browse the repository at this point in the history
  • Loading branch information
makhosi6 committed Jun 1, 2024
2 parents 30ba327 + 9fe6cc9 commit 2451fcc
Show file tree
Hide file tree
Showing 11 changed files with 208 additions and 65 deletions.
30 changes: 28 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,38 @@
# rsa_id_number Change Log

All notable changes to this project will be documented in this file. All changes/updates/entries are not 'breaking changes' unless otherwise mentioned.
This project adheres to [Semantic Versioning](http://semver.org/).
This project adheres to [Semantic Versioning](https://semver.org/).

## 0.0.1 - 2024-01-07

- initial draft

## 0.0.2 - 2024-01-07

- publish with updated description & metadata
- publish with updated description & metadata

## 0.1.5 - 2024-01-08

- fix linter errors and update analysis rules

## 0.1.6 - 2024-01-08

- update the readme file

## 0.1.7 - 2024-01-09

- 'intl': always use the latest version

## 0.1.8 - 2024-01-11

- implement pub.dev recommendations, [see more](https://github.com/makhosi6/rsa_id_number/pull/9)

## [Complete] 1.0.0 - 2024-06-01

### Added
- last and final module to parse id(string) to object
- the package is feature complete, it has all intended functionality(create, validate and parse rsa IDs)

## 1.0.1 - 2024-06-01

- update the docs
34 changes: 31 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@ A Dart package for validating and generating South African ID numbers.

- **Validation**: Validate South African ID numbers based on the specified [format](https://en.wikipedia.org/wiki/South_African_identity_card).
- **Generation**: Generate random South African ID numbers.
- **Parser**: Parse string(ID numbers) to Object

## Installation

Add the following line to your `pubspec.yaml` file:

```yaml
dependencies:
rsa_id_number:
rsa_id_number:
```
Then run:
Expand Down Expand Up @@ -48,8 +49,35 @@ void main() {
import 'package:rsa_id_number/rsa_id_generator.dart';
void main() {
String randomId = RsaIdGenerator.generate();
print('Generated ID: $randomId');
/// generate a random/valid SA id number
final rsaIdNumber = RsaIdGenerator.generate();
log('Generated ID: $rsaIdNumber');
/// generate with options
final rsaIdNumber2 = RsaIdGenerator.generate(
gender: Gender.FEMALE,
citizenship: Citizenship.CITIZEN_BORN,
maxDate: DateTime(1969),
minDate: DateTime.now(),
);
log('Generated ID: $rsaIdNumber2');
}
```

### Parser

```dart
import 'package:rsa_id_number/rsa_id_generator.dart';
void main() {
String idNumber = "8801235121088";
RsaIdParser parser = RsaIdParser.parse(idNumber);
print('Date of Birth: ${parser.dateOfBirth}');
print('Gender: ${parser.sex}');
print('Citizenship: ${parser.citizenship}');
print('Race: ${parser.race}');
print('Is Valid: ${parser.isValid}');
}
```

Expand Down
4 changes: 3 additions & 1 deletion analysis_options.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ include: package:lint/strict.yaml # For production apps
# You might want to exclude auto-generated files from dart analysis
analyzer:
exclude:
- test/*.dart
#- '**.freezed.dart'
#- '**.g.dart'

Expand All @@ -16,7 +17,8 @@ analyzer:
linter:
rules:
# Util classes are awesome!
# avoid_classes_with_only_static_members: false
avoid_classes_with_only_static_members: false
constant_identifier_names: false

# Make constructors the first thing in every class
# sort_constructors_first: true
Expand Down
32 changes: 16 additions & 16 deletions coverage/lcov.info
Original file line number Diff line number Diff line change
Expand Up @@ -45,29 +45,29 @@ LF:32
LH:23
end_of_record
SF:lib/core/rsa_id_parse.dart
DA:13,1
DA:14,3
DA:17,4
DA:18,4
DA:19,4
DA:20,4
DA:21,3
DA:28,1
DA:29,1
DA:30,2
DA:31,2
DA:32,2
DA:37,5
DA:23,1
DA:24,3
DA:27,4
DA:28,4
DA:29,4
DA:30,4
DA:31,3
DA:38,1
DA:39,1
DA:46,1
DA:47,1
DA:40,2
DA:41,2
DA:42,2
DA:47,5
DA:48,1
DA:55,1
DA:49,1
DA:56,1
DA:57,1
DA:58,1
DA:65,1
DA:66,1
DA:67,1
DA:76,1
DA:77,1
LF:23
LH:23
end_of_record
Expand Down
10 changes: 5 additions & 5 deletions example/example.dart
Original file line number Diff line number Diff line change
Expand Up @@ -4,19 +4,19 @@ import 'package:rsa_id_number/rsa_id_number.dart';

void main() {
/// Validate
String idToValidate = '9202204720082';
bool isValid = RsaIdValidator.isValid(idToValidate);
const idToValidate = '9202204720082';
final isValid = RsaIdValidator.isValid(idToValidate);
log('Is valid ID: $isValid');

/// Generation a random/valid SA id number
String rsaIdNumber = RsaIdGenerator.generate();
final rsaIdNumber = RsaIdGenerator.generate();
log('Generated ID: $rsaIdNumber');

/// generate with options
String rsaIdNumber2 = RsaIdGenerator.generate(
final rsaIdNumber2 = RsaIdGenerator.generate(
gender: Gender.FEMALE,
citizenship: Citizenship.CITIZEN_BORN,
maxDate: DateTime(1969, 1, 1),
maxDate: DateTime(1969),
minDate: DateTime.now(),
);
log('Generated with opts: $rsaIdNumber2');
Expand Down
30 changes: 22 additions & 8 deletions lib/core/rsa_id_generator.dart
Original file line number Diff line number Diff line change
@@ -1,19 +1,33 @@
import '../helpers/rsa_id_utils.dart';
import 'package:rsa_id_number/helpers/rsa_id_utils.dart';

/// Generates random valid South African ID numbers or creates new ones based on specified rules.
class RsaIdGenerator {
/// Generates a random valid South African ID number.
///
/// - [gender] parameter specifies the gender ('female' or 'male').
/// - [citizenship] parameter specifies the citizenship ('citizen' or 'resident').
/// - [maxDate] and [minDate] parameters define the date range for generating the birthdate.
/// - maxDate default value is `DateTime(1920)`
/// - minDate default value is `DateTime.now()`
/// Returns a randomly generated valid ID number.
static String generate({
Gender? gender,
Citizenship? citizenship,
DateTime? maxDate,
DateTime? minDate,
}) {
String date = RsaIdUtils.generateDate(maxDate: maxDate, minDate: minDate);
String genderCode = RsaIdUtils.generateGender(gender);
String citizenshipCode = RsaIdUtils.generateCitizenship(citizenship);
int raceDeprecated = 8;

String luhnNr = RsaIdUtils.luhnAppend(
"$date$genderCode$citizenshipCode$raceDeprecated");
// Generate a random birthdate within the specified date range.
final date = RsaIdUtils.generateDate(maxDate: maxDate, minDate: minDate);
// Generate gender codes.
final genderCode = RsaIdUtils.generateGender(gender);
// Generate citizenship codes.
final citizenshipCode = RsaIdUtils.generateCitizenship(citizenship);
// Specify the race code (deprecated).
const raceDeprecated = 8;
// Calculate the checksum digit and construct the final ID number.
final luhnNr = RsaIdUtils.luhnAppend(
"$date$genderCode$citizenshipCode$raceDeprecated",
);
return luhnNr;
}
}
36 changes: 25 additions & 11 deletions lib/core/rsa_id_validator.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
import 'package:luhn_algorithm/luhn_algorithm.dart';
import 'package:meta/meta.dart';

/// Validates South African ID numbers based on specified rules.
class RsaIdValidator {
/// Checks if the provided [idNumber] is a valid South African ID number.
///
/// Returns `true` if the [idNumber] is valid; otherwise, returns `false`.
static bool isValid(String idNumber) {
if (idNumber.length != 13) {
return false;
}

String yymmdd = idNumber.substring(0, 6);
String sequentialNumber = idNumber.substring(6, 10);
String citizenship = idNumber.substring(10, 11);
final yymmdd = idNumber.substring(0, 6);
final sequentialNumber = idNumber.substring(6, 10);
final citizenship = idNumber.substring(10, 11);
// String checksumDigit = idNumber.substring(12, 13);

if (!isValidDate(yymmdd)) {
Expand All @@ -31,11 +35,14 @@ class RsaIdValidator {
return true;
}

/// Validates the date part (YYMMDD) of a South African ID number.
///
/// Returns `true` if the date is valid; otherwise, returns `false`.
@visibleForTesting
static bool isValidDate(String yymmdd) {
int year = int.parse(yymmdd.substring(0, 2));
int month = int.parse(yymmdd.substring(2, 4));
int day = int.parse(yymmdd.substring(4, 6));
final year = int.parse(yymmdd.substring(0, 2));
final month = int.parse(yymmdd.substring(2, 4));
final day = int.parse(yymmdd.substring(4, 6));

if (year < 0 || month < 1 || month > 12 || day < 1 || day > 31) {
return false;
Expand All @@ -44,19 +51,26 @@ class RsaIdValidator {
return true;
}

/// Validates the sequential number part (SSSS) of a South African ID number.
///
/// Returns `true` if the sequential number is valid; otherwise, returns `false`.
@visibleForTesting
static bool isValidSequentialNumber(String sequentialNumber) {
int sequentialDigit = int.parse(sequentialNumber);
return (sequentialDigit >= 0 && sequentialDigit <= 9999);
final sequentialDigit = int.parse(sequentialNumber);
return sequentialDigit >= 0 && sequentialDigit <= 9999;
}

/// Validates the citizenship part (C) of a South African ID number.
///
/// Returns `true` if the citizenship code is valid; otherwise, returns `false`.
@visibleForTesting
static bool isValidCitizenship(String citizenship) {
return citizenship == '0' || citizenship == '1';
}

/// Validates the checksum part (Z) of a South African ID number using the Luhn algorithm.
///
/// Returns `true` if the checksum is valid; otherwise, returns `false`.
@visibleForTesting
static bool isValidChecksum(String idNumber) {
return Luhn.validate(idNumber);
}
static bool isValidChecksum(String idNumber) => Luhn.validate(idNumber);
}
Loading

0 comments on commit 2451fcc

Please sign in to comment.