Commit 89791cbd authored by Alasdair Keyes's avatar Alasdair Keyes

Add in Value objects for Banking BIC/Swift codes

parent 11ba9d31
......@@ -34,6 +34,11 @@ my $invalid_post_code = eval{
* ValueObject::Finance::Money
* ValueObject::Finance::Money::Comma
* ValueObject::Finance::Money::Period
* ValueObject::Finance::BIC
* ValueObject::Finance::BIC::Generic
* ValueObject::Finance::BIC::Passive
* ValueObject::Finance::BIC::Reverse
* ValueObject::Finance::BIC::Test
* ValueObject::Gender
* ValueObject::Identity::UUID
* ValueObject::Identity::UUIDv1
......
package ValueObject::Finance::BIC;
use strict;
use warnings;
use Carp;
use ValueObject::Finance::BIC::Exception::Invalid;
use ValueObject::Finance::BIC::Test;
use ValueObject::Finance::BIC::Passive;
use ValueObject::Finance::BIC::Reverse;
use ValueObject::Finance::BIC::Generic;
use base qw/ ValueObject::Finance::BIC::Base /;
sub new {
my $class = shift;
my $value = shift;
my $bic_object;
foreach my $bic_type ( 'ValueObject::Finance::BIC::Test',
'ValueObject::Finance::BIC::Passive',
'ValueObject::Finance::BIC::Reverse',
'ValueObject::Finance::BIC::Generic') {
$bic_object = eval {
$bic_type->new($value);
};
if ($bic_object) {
return $bic_object;
}
}
croak (ValueObject::Finance::BIC::Exception::Invalid->new($value));
}
1;
=head1 NAME
ValueObject::Finance::BIC - BIC/SWIFT Value Object
=head1 SYNOPSIS
use ValueObject::Finance::BIC;
my $vo = ValueObject::Finance::BIC->new('ABBEGB22XXX');
=head1 DESCRIPTION
ValueObject::Finance::BIC provides Value Object for validation of BIC/SWIFT
codes
Returns one of
ValueObject::Finance::BIC::Test
ValueObject::Finance::BIC::Passive
ValueObject::Finance::BIC::Reverse
ValueObject::Finance::BIC::Generic
or Exception object ValueObject::Finance::BIC::Exception::Invalid
=head1 METHODS
=over 4
=item new($value = '')
Creates a new object
Throws ValueObject::Finance::BIC::Exception::Invalid if $value is invalid
=item validate()
Called during instantiation to validate $value
=item value()
Returns the raw value as passed in at instantiation
=item Finance::BIC()
Returns a Finance::BIC 0 or 1 for no/yes
=back
=head1 SEE ALSO
L<ValueObject::Finance::BIC::OnOff>,
L<ValueObject::Finance::BIC::TrueFalse>
L<ValueObject::Finance::BIC::YesNo>
=cut
package ValueObject::Finance::BIC::Base;
use strict;
use warnings;
use Carp;
use ValueObject::Finance::BIC::Exception::InvalidFormat;
use ValueObject::Finance::BIC::Exception::InvalidCountry;
use ValueObject::Geography::Country::Codes::2Character;
use base qw/ ValueObject::Base /;
my $validation_regex = qr/^([a-z]{4})([a-z]{2})([a-z0-9]{2})([a-z0-9]{3})?$/i;
sub validate_format {
my $self = shift;
my $value = shift || '';
if ($value =~ m/$validation_regex/) {
my ($bank, $country, $location, $branch) = ($1, $2, $3, $4);
eval{
ValueObject::Geography::Country::Codes::2Character->new($country);
} || croak (ValueObject::Finance::BIC::Exception::InvalidCountry->new($value));
return {
bank => $bank,
country => $country,
location => $location,
branch => ($branch || undef)
};
}
croak (ValueObject::Finance::BIC::Exception::InvalidFormat->new($value));
}
1;
=head1 NAME
ValueObject::Finance::BIC::Base - Base object for all Finance::BIC Value Objects
=head1 SYNOPSIS
use base qw/ ValueObject::Finance::BIC::Base /;
sub validate {
my $self = shift;
my $value = shift || '';
# if $value validates
# return 1
# else
# Throw exception on failer
}
=head1 DESCRIPTION
ValueObject::Finance::BIC::Base is a base class from which all
ValueObject::Finance::BIC ValueObjects extend.
The validate() sub routine needs overriding
=head1 METHODS
=over 4
=item validate()
Called during instantiation to validate $value
=item validate_format()
Can be called by inheriting classes to validate the format and country code
part of the BIC
Returns 1 on success
Can throw ValueObject::Finance::BIC::Exception::InvalidCountry
ValueObject::Finance::BIC::Exception::InvalidFormat
=back
=head1 SEE ALSO
L<Carp>,
L<ValueObject::Finance::BIC::Base>
=cut
package ValueObject::Finance::BIC::Exception::Invalid;
use strict;
use warnings;
use base qw/ ValueObject::Exception::Base /;
sub new {
my $class = shift;
my $message = 'Invalid BIC';
return $class->SUPER::new($message, @_);
}
1;
package ValueObject::Finance::BIC::Exception::InvalidCountry;
use strict;
use warnings;
use base qw/ ValueObject::Exception::Base /;
sub new {
my $class = shift;
my $message = 'Invalid country for BIC';
return $class->SUPER::new($message, @_);
}
1;
package ValueObject::Finance::BIC::Exception::InvalidFormat;
use strict;
use warnings;
use base qw/ ValueObject::Exception::Base /;
sub new {
my $class = shift;
my $message = 'Invalid format for BIC';
return $class->SUPER::new($message, @_);
}
1;
package ValueObject::Finance::BIC::Exception::InvalidPassive;
use strict;
use warnings;
use base qw/ ValueObject::Exception::Base /;
sub new {
my $class = shift;
my $message = 'Invalid passive BIC';
return $class->SUPER::new($message, @_);
}
1;
package ValueObject::Finance::BIC::Exception::InvalidReverse;
use strict;
use warnings;
use base qw/ ValueObject::Exception::Base /;
sub new {
my $class = shift;
my $message = 'Invalid reverse BIC';
return $class->SUPER::new($message, @_);
}
1;
package ValueObject::Finance::BIC::Exception::InvalidTest;
use strict;
use warnings;
use base qw/ ValueObject::Exception::Base /;
sub new {
my $class = shift;
my $message = 'Invalid test BIC';
return $class->SUPER::new($message, @_);
}
1;
package ValueObject::Finance::BIC::Generic;
use strict;
use warnings;
use Carp;
use base qw/ ValueObject::Finance::BIC::Base /;
sub validate {
my $self = shift;
my $value = shift || '';
## Validate format from parent module, on error rethrow
my $parts = eval {
$self->validate_format($value);
} || croak ([email protected]);
croak (ValueObject::Finance::BIC::Exception::Invalid->new($value))
if ($parts->{ location } =~ /^.(0|1|2)$/);
return 1;
}
1;
=head1 NAME
ValueObject::Finance::BIC::Generic - Value object for Generic BIC codes
=head1 SYNOPSIS
use ValueObject::Finance::BIC::Generic;
my $vo = ValueObject::Finance::BIC::Generic->new('DEUTDEFF');
=head1 DESCRIPTION
ValueObject::Finance::BIC::Generic provides Value Object for validation of BIC
codes, trditionally with the 2nd character of the location as '1'
=head1 METHODS
=over 4
=item new($value = '')
Creates a new object
Throws ValueObject::Finance::BIC::Exception::Invalid
ValueObject::Finance::BIC::Exception::InvalidFormat
ValueObject::Finance::BIC::Exception::InvalidCountry
=item validate()
Called during instantiation to validate $value
=item value()
Returns the raw value as passed in at instantiation
=back
=head1 SEE ALSO
L<ValueObject::Finance::BIC::Base>
=cut
package ValueObject::Finance::BIC::Passive;
use strict;
use warnings;
use Carp;
use ValueObject::Finance::BIC::Exception::InvalidPassive;
use base qw/ ValueObject::Finance::BIC::Base /;
sub validate {
my $self = shift;
my $value = shift || '';
## Validate format from parent module, on error rethrow
my $parts = eval {
$self->validate_format($value);
} || croak ([email protected]);
croak (ValueObject::Finance::BIC::Exception::InvalidPassive->new($value))
unless ($parts->{ location } =~ /^.1$/);
return 1;
}
1;
=head1 NAME
ValueObject::Finance::BIC::Passive - Value object for Passive BIC codes
=head1 SYNOPSIS
use ValueObject::Finance::BIC::Passive;
my $vo = ValueObject::Finance::BIC::Passive->new('DEUTDEF1XXX');
=head1 DESCRIPTION
ValueObject::Finance::BIC::Passive provides Value Object for validation of
passive BIC codes, trditionally with the 2nd character of the location as '1'
=head1 METHODS
=over 4
=item new($value = '')
Creates a new object
Throws ValueObject::Finance::BIC::Exception::InvalidPassive
ValueObject::Finance::BIC::Exception::InvalidFormat
ValueObject::Finance::BIC::Exception::InvalidCountry
=item validate()
Called during instantiation to validate $value
=item value()
Returns the raw value as passed in at instantiation
=back
=head1 SEE ALSO
L<ValueObject::Finance::BIC::Base>
=cut
package ValueObject::Finance::BIC::Reverse;
use strict;
use warnings;
use Carp;
use ValueObject::Finance::BIC::Exception::InvalidReverse;
use base qw/ ValueObject::Finance::BIC::Base /;
sub validate {
my $self = shift;
my $value = shift || '';
## Validate format from parent module, on error rethrow
my $parts = eval {
$self->validate_format($value);
} || croak ([email protected]);
croak (ValueObject::Finance::BIC::Exception::InvalidReverse->new($value))
unless ($parts->{ location } =~ /^.2$/);
return 1;
}
1;
=head1 NAME
ValueObject::Finance::BIC::Reverse - Value object for Reverse BIC codes
=head1 SYNOPSIS
use ValueObject::Finance::BIC::Reverse;
my $vo = ValueObject::Finance::BIC::Reverse->new('DEUTDEF2');
=head1 DESCRIPTION
ValueObject::Finance::BIC::Passive provides Value Object for validation of Reverse
BIC codes, trditionally with the 2nd character of the location as '0'
=head1 METHODS
=over 4
=item new($value = '')
Creates a new object
Throws ValueObject::Finance::BIC::Exception::InvalidReverse
ValueObject::Finance::BIC::Exception::InvalidFormat
ValueObject::Finance::BIC::Exception::InvalidCountry
=item validate()
Called during instantiation to validate $value
=item value()
Returns the raw value as passed in at instantiation
=back
=head1 SEE ALSO
L<ValueObject::Finance::BIC::Base>
=cut
package ValueObject::Finance::BIC::Test;
use strict;
use warnings;
use Carp;
use ValueObject::Finance::BIC::Exception::InvalidTest;
use base qw/ ValueObject::Finance::BIC::Base /;
sub validate {
my $self = shift;
my $value = shift || '';
## Validate format from parent module, on error rethrow
my $parts = eval {
$self->validate_format($value);
} || croak ([email protected]);
croak (ValueObject::Finance::BIC::Exception::InvalidTest->new($value))
unless ($parts->{ location } =~ /^.0$/);
return 1;
}
1;
=head1 NAME
ValueObject::Finance::BIC::Test - Value object for Test BIC codes
=head1 SYNOPSIS
use ValueObject::Finance::BIC::Test;
my $vo = ValueObject::Finance::BIC::Test->new('DEUTDEF0XXX');
=head1 DESCRIPTION
ValueObject::Finance::BIC::Passive provides Value Object for validation of Test
BIC codes, trditionally with the 2nd character of the location as '0'
=head1 METHODS
=over 4
=item new($value = '')
Creates a new object
Throws ValueObject::Finance::BIC::Exception::InvalidTest
ValueObject::Finance::BIC::Exception::InvalidFormat
ValueObject::Finance::BIC::Exception::InvalidCountry
=item validate()
Called during instantiation to validate $value
=item value()
Returns the raw value as passed in at instantiation
=back
=head1 SEE ALSO
L<ValueObject::Finance::BIC::Base>
=cut
#!/usr/bin/env perl
use strict;
use warnings;
use Test::More tests => 30;
use Test::Exception;
use FindBin qw($Bin);
use lib "$Bin/../lib";
# Setup
require_ok('ValueObject::Finance::BIC');
require_ok('ValueObject::Finance::BIC::Test');
require_ok('ValueObject::Finance::BIC::Passive');
require_ok('ValueObject::Finance::BIC::Reverse');
require_ok('ValueObject::Finance::BIC::Generic');
my $test_bic = 'ABBEGB20XXX';
my $passive_bic = 'ABBEGB21XXX';
my $reverse_bic = 'ABBEGB22XXX';
my $generic_bic = 'ABBEGB24XXX';
my $test_bic_vo = ValueObject::Finance::BIC::Test->new($test_bic);
my $passive_bic_vo = ValueObject::Finance::BIC::Passive->new($passive_bic);
my $reverse_bic_vo = ValueObject::Finance::BIC::Reverse->new($reverse_bic);
my $generic_bic_vo = ValueObject::Finance::BIC::Generic->new($generic_bic);
my $bic_vo = ValueObject::Finance::BIC->new($generic_bic);
# Instantiation Test
isa_ok($test_bic_vo, 'ValueObject::Finance::BIC::Test');
isa_ok($test_bic_vo, 'ValueObject::Finance::BIC::Base');
isa_ok($passive_bic_vo, 'ValueObject::Finance::BIC::Passive');
isa_ok($passive_bic_vo, 'ValueObject::Finance::BIC::Base');
isa_ok($reverse_bic_vo, 'ValueObject::Finance::BIC::Reverse');
isa_ok($reverse_bic_vo, 'ValueObject::Finance::BIC::Base');
isa_ok($generic_bic_vo, 'ValueObject::Finance::BIC::Generic');
isa_ok($generic_bic_vo, 'ValueObject::Finance::BIC::Base');
isa_ok($bic_vo, 'ValueObject::Finance::BIC::Generic');
isa_ok($bic_vo, 'ValueObject::Finance::BIC::Base');
## Test return values
ok($test_bic_vo->value() eq $test_bic, "value function for object '$test_bic'");
ok($test_bic_vo eq $test_bic, "stringify for object '$test_bic'");
ok($passive_bic_vo->value() eq $passive_bic, "value function for object '$passive_bic'");
ok($passive_bic_vo eq $passive_bic, "stringify for object '$passive_bic'");
ok($reverse_bic_vo->value() eq $reverse_bic, "value function for object '$reverse_bic'");
ok($reverse_bic_vo eq $reverse_bic, "stringify for object '$reverse_bic'");
ok($generic_bic_vo->value() eq $generic_bic, "value function for object '$generic_bic'");
ok($generic_bic_vo eq $generic_bic, "stringify for object '$generic_bic'");
ok($bic_vo->value() eq $generic_bic, "value function for object '$generic_bic'");
ok($bic_vo eq $generic_bic, "stringify for object '$generic_bic'");
## Test Exceptions
throws_ok { ValueObject::Finance::BIC::Test->new('ABBEGB29XXX') }
'ValueObject::Finance::BIC::Exception::InvalidTest',
'Invalid Test exception for ValueObject::Finance::BIC::Test';
throws_ok { ValueObject::Finance::BIC::Passive->new('ABBEGB29XXX') }
'ValueObject::Finance::BIC::Exception::InvalidPassive',
'Invalid Passive exception for ValueObject::Finance::BIC::Passive';
throws_ok { ValueObject::Finance::BIC::Reverse->new('ABBEGB29XXX') }
'ValueObject::Finance::BIC::Exception::InvalidReverse',
'Invalid Reverse exception for ValueObject::Finance::BIC::Reverse';
throws_ok { ValueObject::Finance::BIC::Generic->new('ABBEGB20X') }
'ValueObject::Finance::BIC::Exception::InvalidFormat',
'Invalid Format exception for ValueObject::Finance::BIC::Generic';
throws_ok { ValueObject::Finance::BIC::Generic->new('ABBEXX20XXX') }
'ValueObject::Finance::BIC::Exception::InvalidCountry',
'Invalid Country exception for ValueObject::Finance::BIC::Generic';
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment