File Coverage

blib/lib/Business/NAB/AccountInformation/Group.pm
Criterion Covered Total %
statement 56 59 94.9
branch 10 14 71.4
condition n/a
subroutine 12 12 100.0
pod 3 3 100.0
total 81 88 92.0


line stmt bran cond sub pod time code
1             package Business::NAB::AccountInformation::Group;
2             $Business::NAB::AccountInformation::Group::VERSION = '0.03';
3             =head1 NAME
4              
5             Business::NAB::AccountInformation::Group
6              
7             =head1 SYNOPSIS
8              
9             use Business::NAB::AccountInformation::Group;
10              
11             my $Group = Business::NAB::AccountInformation::Group->new(
12             ultimate_receiver_identification => $ult_receiver_id,
13             originator_identification => $org_id,
14             as_of_date => $as_of_date,
15             additional_field => $additional_field,
16             control_total_a => $total_a,
17             number_of_accounts => $number_of_accounts,
18             control_total_b => $total_b,
19             );
20              
21             =head1 DESCRIPTION
22              
23             Class for parsing a NAB "Account Information File (NAI/BAI2)" group
24             line (type C<02>).
25              
26             =cut
27              
28 2     2   1361712 use strict;
  2         5  
  2         113  
29 2     2   11 use warnings;
  2         5  
  2         162  
30 2     2   13 use feature qw/ signatures state /;
  2         4  
  2         299  
31 2     2   14 use Carp qw/ croak /;
  2         6  
  2         138  
32              
33 2     2   644 use Moose;
  2         574847  
  2         19  
34 2     2   20146 use Moose::Util::TypeConstraints;
  2         5  
  2         25  
35 2     2   6333 no warnings qw/ experimental::signatures /;
  2         6  
  2         169  
36              
37 2     2   1353 use Text::CSV_XS qw/ csv /;
  2         22419  
  2         205  
38 2         2033 use Business::NAB::Types qw/
39             add_max_string_attribute
40 2     2   842 /;
  2         11  
41              
42             =head1 ATTRIBUTES
43              
44             =over
45              
46             =item ultimate_receiver_identification (Str, max length 4096)
47              
48             =item originator_identification (Str, max length 8)
49              
50             =item as_of_date (DateTime)
51              
52             =item additional_field
53              
54             =item control_total_a (Int)
55              
56             =item number_of_accounts (Int)
57              
58             =item control_total_b (Int)
59              
60             =item number_of_records (Int)
61              
62             =item accounts (ArrayRef[Business::NAB::AccountInformation::Account])
63              
64             =back
65              
66             =cut
67              
68             foreach my $str_attr (
69             'ultimate_receiver_identification[4096]',
70             'originator_identification[8]',
71             'additional_field[4096]',
72             ) {
73             __PACKAGE__->add_max_string_attribute(
74             $str_attr,
75             is => 'ro',
76             required => 1,
77             );
78             }
79              
80             has 'as_of_date' => (
81             isa => 'NAB::Type::StatementDate',
82             is => 'ro',
83             required => 1,
84             coerce => 1,
85             );
86              
87             has [
88             qw/
89             control_total_a
90             number_of_accounts
91             control_total_b
92             number_of_records
93             /
94             ] => (
95             isa => 'Int',
96             is => 'rw',
97             );
98              
99             subtype "Accounts"
100             => as "ArrayRef[Business::NAB::AccountInformation::Account]";
101              
102             has 'accounts' => (
103             traits => [ 'Array' ],
104             is => 'rw',
105             isa => 'Accounts',
106             default => sub { [] },
107             handles => {
108             "add_account" => 'push',
109             },
110             );
111              
112             =head1 METHODS
113              
114             =head2 new_from_raw_record
115              
116             Returns a new instance of the class with attributes populated from
117             the result of parsing the passed line:
118              
119             my $Group = Business::NAB::AccountInformation::Group
120             ::Payments::DescriptiveRecord->new_from_raw_record( $line );
121              
122             =cut
123              
124 2     2 1 3090 sub new_from_raw_record ( $class, $line ) {
  2         7  
  2         5  
  2         4  
125              
126 2 50       17 my $aoa = csv( in => \$line )
127             or croak( Text::CSV->error_diag );
128              
129 2         1444 return $class->new_from_record( $aoa->[ 0 ]->@* );
130             }
131              
132             =head2 new_from_record
133              
134             Returns a new instance of the class with attributes populated from
135             the result of parsing the already parsed line:
136              
137             my $Group = Business::NAB::AccountInformation::Group
138             ::Payments::DescriptiveRecord->new_from_record( @record );
139              
140             =cut
141              
142 5     5 1 12 sub new_from_record ( $class, @record ) {
  5         12  
  5         18  
  5         10  
143              
144             my (
145 5         20 $record_type,
146             $ult_receiver_id,
147             $org_id,
148             undef, # group status
149             $as_of_date,
150             undef, # as of time
151             $additional_field,
152             ) = @record;
153              
154 5 100       19 if ( $record_type ne '02' ) {
155 1         28 croak( "unsupported record type ($record_type)" );
156             }
157              
158 4         178 return $class->new(
159             ultimate_receiver_identification => $ult_receiver_id,
160             originator_identification => $org_id,
161             as_of_date => $as_of_date,
162             additional_field => $additional_field,
163             );
164             }
165              
166             =head2 validate_totals
167              
168             Checks if the control_total_a and control_total_b values match the
169             expected totals of the contained accounts:
170              
171             $Group->validate_totals( my $is_bai2 = 0 );
172              
173             Will throw an exception if any total doesn't match the expected value.
174              
175             Takes an optional boolean param to stipulate if the file type is BAI2
176             (defaults to false).
177              
178             =cut
179              
180 4     4 1 31 sub validate_totals ( $self, $is_bai2 = 0 ) {
  4         7  
  4         7  
  4         5  
181              
182 4         156 my $num_accounts = scalar( $self->accounts->@* );
183 4 50       123 croak(
184             "number of nested accounts ($num_accounts) != number_of_accounts "
185 0         0 . "(@{[ $self->number_of_accounts ]})"
186             ) if $num_accounts != $self->number_of_accounts;
187              
188 4         15 my ( $account_total_a, $account_total_b ) = ( 0, 0 );
189              
190 4         134 foreach my $Account ( $self->accounts->@* ) {
191 9         281 $account_total_a += $Account->control_total_a;
192              
193 9 100       20 if ( !$is_bai2 ) {
194 4         144 $account_total_b += $Account->control_total_b;
195             }
196             }
197              
198             croak(
199 4 50       164 "calculated sum ($account_total_a) != control_total_a "
200 0         0 . "(@{[$self->control_total_a]})"
201             ) if $account_total_a != $self->control_total_a;
202              
203 4 100       11 if ( !$is_bai2 ) {
204 2 50       74 croak(
205             "calculated sum ($account_total_b) != control_total_b "
206 0         0 . "(@{[$self->control_total_b]})"
207             ) if $account_total_b != $self->control_total_b;
208             }
209              
210 4         15 return 1;
211             }
212              
213             =head1 SEE ALSO
214              
215             L<Business::NAB::Types>
216              
217             L<Business::NAB::AccountInformation::Account>
218              
219             L<Business::NAB::AccountInformation::Transaction>
220              
221             =cut
222              
223             __PACKAGE__->meta->make_immutable;